My Code concepts series has been working towards an overall point: In a few months, we’ll put together some of the lessons we’ve learned into an insanely awesome, custom rules engine. In fact, it is going to be so amazing, that it is actually going to write itself. (Catch up on previous columns in the series: Code concepts: C#’s extension methods and Code concepts: C#’s var keyword.) But, for now, I’ll focus on lambdas in .NET, specifically what lambdas are and how to use them.

What are lambdas?

A lambda is a shortcut for writing an anonymous method. Functionally speaking, lambdas serve the same purpose as anonymous functions and have a much cleaner syntax. Lambdas are assigned with the => operator. Lambdas are delegates and can be used in place of them. Lambdas with no return type are equal to the generic Action<T> type, and lambdas with a return type are equal to the Func<T> type.

When creating the lambda, you need three elements: a variable to assign the lambda to, a parameter list, and a method body.

  • A variable to assign the lambda to: This can be a specific delegate type or one of the two generic delegate types.
  • A parameter list: If there are multiple input parameters, this list must be enclosed in parentheses, and the parameters must be separated by commas. If there is only one parameter, the parentheses are optional. You may omit the types, since the compiler can infer the types based on the variable declaration.
  • A method body: This must be enclosed in curly braces if it is more than one statement. If you use the curly braces, you need a statement terminator (a semicolon) after the braces.

You may be wondering why I’m talking about curly braces as if VB.NET doesn’t exist. Unfortunately, at this time, lambdas are essentially useless in VB.NET because VB.NET cannot resolve lambdas that span more than one line. The next version of VB.NET (Visual Basic 10 in .NET 4) will support multiple line lambdas through its new automatic statement continuation feature.

Let’s take a look at a very simple lambda to get the feel for the syntax:

Func<int, int, string> simpleLambda1 = (input1, input2)

 => String.Format("{0} times {1} = {2}",

input1, input2,input1*input2);

This creates a lambda that accepts two integers (assigned to the local variables input1 and input2) and returns a string.

Any variables declared within the lambda are local to it and not visible outside of it. When the lambda is declared, any variables that it uses that are declared outside of the lambda are “captured” by the lambda and “travel” with it, even if the lambda is later executed in a scope that contains a variable by the same name with the same signature. Here is some sample code:

static void RunLambda(Action<int> lambdaToRun)

{

    int multiplier = 2;
    Console.WriteLine("Running the lambda remotely.");

    for (int counter = 0; counter < 10; counter++)

    {

        multiplier++;

        lambdaToRun(counter);

    }

}
static void Main()

{

    int multiplier = 5;

    Action<int> lambda =

        input => Console.WriteLine("{0} times {1} = {2}", input, multiplier, input*multiplier);

   

    Console.WriteLine("Running the lambda locally.");

    for (int counter = 0; counter < 10; counter++)

    {

        multiplier++;

        lambda(counter);

    }
    RunLambda(lambda);
    Console.WriteLine("Press Enter to quit...");

    Console.ReadLine();

}

Looking at this code, you might initially expect to see that when RunLambda() is executed, the value of 2 is used for the multiplier variable, but you’d be wrong. Figure A shows the actual output.
Figure A

The value of 15 carried through to the called function. This is a very important observation.

Why would we prefer a lambda to a full function? For one thing, lambdas are portable. As you can see, lambdas are easily passed around — to do this with a normal function would involve the clumsy and indirect delegate syntax. For another thing, lambdas are quite concise at a syntax level. The syntax allows the developer to focus on the lambda’s contents, not all of the code needed to construct it. The big difference is in convenience. Because the lambda syntax is so easy to use, you find yourself doing things that you would never do with delegates, just because it no longer feels like a chore.

Summary

This is a brief introduction to lambdas. When I put all of these pieces together into a rule engine, you’ll really see how useful lambdas are in practice.

For a more detailed explanation about lambdas, read the C# 3.0 language specification (in Word format), especially section 7.14.

J.Ja

Disclosure of Justin’s industry affiliations: Justin James has a contract with Spiceworks to write product buying guides.

—————————————————————————————

Get weekly development tips in your inbox
Keep your developer skills sharp by signing up for TechRepublic’s free Web Developer newsletter, delivered each Tuesday. Automatically subscribe today!