Lambda expressions

With extension methods and anonymous methods (or inline methods), Visual Studio introduces an expression called the lambda expression.

A lambda expression is actually a syntax change for anonymous methods. It is just another way of writing anonymous methods.

Now, let's learn what a lambda expression is, step by step.

First we need to understand what a delegate is. A delegate is a type that references a method, which means you can define a delegate and then assign a method to it. Once a delegate is assigned a method, it behaves exactly like that method. The delegate method can be used like any other method, with parameters and a return value.

In C# there is a generic delegate type, Func<A,R>, which represents a function taking an argument of type A and returning a value of type R:

delegate R Func<A,R> (A Arg);

In fact there are several overloaded versions of Func, of which Func<A,R> is one.

Now we will use this generic delegate type to define an extension method in our extension class MyExtensions:

public static IEnumerable<T> Get<T>(this IEnumerable<T> source, Func<T, bool> predicate)
{
    foreach (T item in source)
    {
       if (predicate(item))
           yield return item;
    }
}

This extension method will apply to any object that extends the IEnumerable interface and has one parameter of type Func, which you can think of as a pointer to a function. This parameter function is the predicate to specify the criteria for the selection. This method will return a list of objects that match the predicate criteria.

Note

Make sure you define this method within the extension class MyExtensions, not within the main class Program.

Now we can create a new function as the predicate in our main class, just after the Main method:

public static bool IsVege(Product p)
{
    return p.ProductName.Contains("vegetable");
}

Then we can use the extension method Get, to retrieve all of the vegetable products, as follows:

var veges1 = products.Get(IsVege);

In previous sections, we created a products list with five products, of which two are vegetables. So veges1 is actually of the IEnumerable<Product> type and should contain two products. We can write the following test statements to print out the results:

Console.WriteLine("
There are {0} vegetables:", veges1.Count());
foreach (var p in veges1)
{
    Console.WriteLine("Product ID: {0}  Product name: {1}", 
                       p.ProductID, p.ProductName);
}

The output will be as follows:

Lambda expressions

Or we can first create a new variable of type Func, assign the function pointer of IsVege to this new variable, and then pass this new variable to the Get method as shown in the following code snippet:

Func<Product, bool> predicate = IsVege;
var veges2 = products.Get(predicate);

The veges2 variable will contain the same products as veges1.

Now let us use the Contains anonymous method to rewrite the above statement, which will now become the following:

var veges3 = products.Get(
    delegate (Product p)
    {
        return p.ProductName.Contains("vegetable");
    }
);

At this time, we put the body of the predicate method IsVege inside the extension method call with the keyword delegate. In order to get the vegetables from the products list, we don't have to define a specific predicate method. We can specify the criteria on the spot when we need it.

The lambda expression comes into play right after the preceding step. In C# 3.0 and above, using a lambda expression, we can actually write the following one-line statement to retrieve all of the vegetables from the products list:

var veges4 = products.Get(p => p.ProductName.Contains("vegetable"));

In the preceding statement, the parameter of the Get method is a lambda expression. The first p is the parameter of the lambda expression, just like the parameter p in the anonymous method when we get veges3. This parameter is implicitly typed and in this case it is of the type Product, because this expression is applied to a Products object, which contains a list of the Product objects. This parameter can also be explicitly typed as follows:

var veges5 = products.Get((Product p) => p.ProductName.Contains("vegetable"));

The parameter is followed by the => token and then followed by an expression or a statement block, which will be the predicate.

The => token here is called the lambda operator. It is used in lambda expressions to separate the input variables on the left side from the lambda body on the right side. This operator is read as "goes to".

So now, we can easily write the following statement to get all of the candy products:

var candies = products.Get(p => p.ProductName.Contains("candy"));

At compile time, all lambda expressions are translated into anonymous methods according to the lambda expression conversion rules. So again, this feature is only a Visual Studio compiler feature. We don't need any special .NET runtime libraries or instructions to run an assembly containing lambda expressions.

In short, lambda expressions are just another way of writing anonymous methods in a more concise, functional syntax.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset