Using LINQ in your applications has a handful of prerequisites. A programmer confident with LINQ needs to understand Lambda Expressions, Anonymous Types, Extension Methods, Type Inference, Type Initialization, and most likely Expression Trees too. While this seems like a long list, most of the items are things that you already know, but with a little twist. At the core of LINQ are lambda expressions. Lambda expressions are how you apply your business logic using LINQ constructs. Despite having a cool name, lambda expressions are little more than short-hand for defining a delegate.

A delegate is a type that references a method. Any method that matches the delegate's signature (return type and parameters) can be assigned to it. Common uses for delegates are for sorting, filtering, or manipulating data. In the .NET framework, delegates are the basis for event handling and have been around since the Framework 1.0 days. As the .NET Framework has evolved, delegates have remained fundamentally the same, but because of language enhancements and compiler magic the syntax has become something quite useful - Lambda Expressions.
Before .NET 2.0 Framework
In the beginning there were Named Methods. Using named methods required a decent amount of code. You had to first define the delegate:
public delegate bool IntFilter(int value);
Then write a method or methods that matched the delegate's signature.
public bool IsEven(int value)
{
return (value % 2 == 0);
}
Then instantiate and use the delegate.
IntFilter filter = IsEven;
bool match = filter(1); // false
filter = IsOdd;
match = filter(1); // true
This example clearly illustrates the three steps for using delegates. 1.) Define a delegate. 2.) Define a method. 3.) Instantiate the delegate with your method. Where you'll see this most often is in event handling. Below, System.EventHandler is the Delegate and button1_Click is the named method that is assigned to instantiate the EventHandler.
button1.Click += new System.EventHandler(this.button1_Click);
private void button1_Click(object sender, EventArgs e)
{
// Handle the button click
}
Enter the 2.0 Framework
When Microsoft released the .NET 2.0 Framework they introduced some compiler magic called anonymous methods. Anonymous methods allowed you to instantiate a delegate by defining your method inline. Anonymous methods reduce the extra coding effort of writing a separate method when there really isn't a need for it.
IntFilter filter = delegate(int value) { return (value % 2 == 0); };
I say that this is compiler magic because if you look at your project in a tool like .NET Reflector, you'll see a method defined on your class similar to this.
[CompilerGenerated]
private static bool b__0(int value)
{
return ((value % 2) == 0);
}
Some subtle but important rules apply to variable scoping in anonymous methods. Parameters and variables defined within the anonymous method's code block are scoped to the code block. If a variable external to the code block is referenced from within the code block, it is said to be captured. Captured variables will not be disposed of until the delegate goes out of scope.
// threshold will NOT be garbage collected until f goes out of scope
int threshold = 5;
IntFilter f = delegate(int value) { return value < threshold; };
The 3.0 Framework introduces Lambda Expressions
Lambda Expressions use the lambda operator => (pronounced "goes to") to create delegates or expression trees. Think of them as shorthand for anonymous methods. The syntax is (parameters) => { statements; }. When only one parameter exists the parenthesis are optional. When more than one parameter exists they are separated by commas.
// Func<> and Action<> are two new Generic Delegates that support up to
// four input parameters. Func<> returns a value, Action<> does not.
Func<bool> noParams = () => { return true; };
Func<int, bool> oneParam = (int value) => { return value > 5; };
Func<int, int, bool> twoParams = (int value, int threshold) => { return value > threshold; };
| | Statement Lambda | Expression Lambda |
| Create Expression Trees |
No |
Yes |
| Instantiate Delegates |
Yes |
Yes |
I digress...
There are actually two flavors of lambda expressions: Statement Lambdas and Expression Lambdas. Statement lambdas use curly brackets and contain more than one statement. Expression lambdas do not use curly brackets and contain only one statement. Statement lambdas cannot be used to create expression trees, expression lambdas can. Both can be used to instantiate delegates. This post discusses statement lambdas.
Where lambda expressions really become useful is in LINQ. LINQ provides a set of extension methods to the IEnumerable<> interface that can be used for sorting, filtering, and manipulating the contents of an IEnumerable<>. Below is a graphic with code examples of using the LINQ Where() extension method to filter an array of integers down to just the even integers. I have highlighted the syntactical differences between using named methods, anonymous methods, and lambda expressions. Hopefully this helps illustrate the convenience that lambda expressions bring to the party and takes away some of the "magic" that can make learning lambda expressions confusing. The examples are ordered chronologically to show how the syntax has evolved to become more concise.

As always the best way to learn something is to play with it. To run these samples you'll need a project that targets the .NET 3.5 Framework and you'll need to add a using statement for the System.Linq (in System.Core.dll, Version 3.5) namespace.