1. Computing

LINQ Tutorial Two - Lambda Expressions

By

This is the second of a series of tutorials about LINQ. If you've not read the first on, start with:

Having covered Extension Methods, Anonymous Types and Methods and looked briefly at Lambda Expressions in the first tutorial, we can start looking at what LINQ is and how to ue it. But before that, a little bit more on Lambda Expressions.

A lambda expression is an anonymous function that can contain expressions and statements, and you can use it to create delegates or expression tree types. This example below is a delegate:

     class Program
    {
        delegate int del(int n) ;
        static void Main(string[] args)
        {
            del aDelegate = x => x * 3;
            var i = aDelegate(10) ;
             Console.WriteLine("i={0}",i) ; // 30
            Console.ReadKey() ;
         }
     }

This outputs i=30. Read this as del being a signature of a delegate which takes an int parameter and returns an int. This is an expression lambda and is useful in LINQ because it lets us specify a function that can be used as the basis of a selection. We'll come back to that in the next tutorial.

Here the aDelegate function multiplies x by 3. It's just a function so we call it and pass in a value 10 and it returns 30.

The other use of Lambdas is in expression tree types but that will be covered in the next tutorial.

Complicated Expressions and Statements

There are certain parts in LINQ and Lambda expressions that look complicated and the different ways of expressing Lambda expressions and statements is certainly not the easiest to understand. The general look of an Lambda expression is

(input parameters) => expression

We saw that x => x * 3. The input parameter x is multiplied by three. Unfortunately the declaration of the delegate slightly complicates things. In the example above we never use the value n, the delegate's input parameter. It might be better had it just been

delegate int del(int); // wrong invalid syntax

But you must name the parameter even though it's never explicitly used like this.

delegate int del(int n);

When there's just one parameter to the Lambda expression you can drop the brackets so that's why it's

x => x* 3

instead of

(x) => x* 3 // this is also valid

Multiple Parameters

In this example, there are two int parameters i and j and the aDelegate function

delegate int del(int i,int j);
static void Main(string[] args)
{
   del aDelegate = (x,y) => x*3 + y*y;
   var i = aDelegate(10,5);
   Console.WriteLine("i={0}",i); // 30
   Console.ReadKey();
}

This outputs i=55 because 10 x 3 + 5 x 5 = 55. (Multiplications are always done before addition). Likewise you can specify zero params. It's not much use but this works so long as you use empty brackets ().

delegate int del();
static void Main(string[] args)
{
   del aDelegate = () => int.MinValue;
   var i = aDelegate()+1;
   Console.WriteLine("i={0}",i);
   Console.ReadKey();
}

This outputs i=-2147483647.

Statement Lambdas

The above examples are expression lambdas that return a value but there are also statement lambdas. These have the form:

(input Parameters) => {statement;}

These are less useful that Lambda expressions because they don't return a value. You can use them for instance to call a delegate.

public delegate void OutputToConsole(string arg);

private static void Main(string[] args)
  {
   OutputToConsole OutConsole = a =>
     {
     Console.WriteLine(a);
    };
   OutConsole("Good Morning");
   Console.ReadKey();
  }

LINQ and Lambdas

LINQ allows you to select items out of a list and optionally transform them. The list can be a list of objects, of records from a SQL database, or XML. Part of doing this is the ability to select items out of the list. We'll see how that is done shortly but it's importnat to note that we can use Lambda expressions to do this selection.

There is a method with one parameter that returns a value of the type sepecified by the TResult parameter. This is the Func.

public static void Main()
{
   Func convert = s => s.ToLower();
   var MyName = "David Bolton";
   Console.WriteLine(convert(MyName));
   Console.ReadKey();
}

Here the Lambda expression is assigned to a delegate that accepts a parameters string and returns one. The Lambda expression type is compatible with the Func<T,Tresult> delegate so no explicit delegate has to be defined.

Let's look at this applied to a simple selector delegate. public static void Main()
{
   var values = new int[] {1, 3, 4, 7, 9, 11, 3, 15};
   Func<int,int> selector = i => i % 3==0?i:0;
   var processedvalues = values.Select(selector);
   foreach( var avalue in processedvalues)
   Console.WriteLine("{0}",avalue);
   Console.ReadKey();
}

This processes a list of ints and if the number isn't exactly divisible by 3 as in !(i% 3==0) then a 0 is returned. It outputs (on separate lines) the numbers 0 3 0 0 9 0 3 15.

More Generic Delegates!

We've seen the one Func delegate but what if there are two or three or even sixteen parameters. Well the good news is that there are sixteen different Func<T..) delegates. The first we've seen Func<T,TResult>, the next one is Func<T1,T2,Result> and they go all the way out to Func<T1,T2,T3,T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, TResult>. Don't believe it? See 16 Parameters Delegates.

Conclusion

This concludes this tutorial on Lambda Expressions which are a very compact and handy way of providing anonymous functionality. The next tutorial will start on LINQ properly, selecting, sorting, grouping and presenting and using Lambda expressions.

  1. About.com
  2. Computing
  3. C / C++ / C#
  4. C# / C Sharp
  5. Learn C Sharp
  6. LINQ Tutorial #2 - About Lambda Expressions

©2014 About.com. All rights reserved.