Quote
A lambda expression is an anonymous function that can contain expressions and statements, and can be used to create delegates or expression tree types.
Ok, so what does that mean? Here's a good read on the evolution of anonymous methods in C#.
Anyway, an anonymous method is exactly what it sounds like. It's a method that is not named. They can be quite useful in certain situations, especially when you need to provide a method that can be quite short and doesn't need to be re-usable.
So, a common task: show a message box when you click a button. Old code that most of us know how to write:
public Form1()
{
InitializeComponent();
Button b1 = new Button() { Text = "Button" };
this.Controls.Add(b1);
b1.Click += new EventHandler(b1_Click);
}
void b1_Click(object sender, EventArgs e)
{
throw new NotImplementedException();
}
Easy enough, but why do I need to write a named method for one button? It takes up space and it doesn't need to be re-used for anything else.
So, a "better" (in this case, shorter) way to do it might be this:
public Form1()
{
InitializeComponent();
Button b1 = new Button() { Text = "Button" };
this.Controls.Add(b1);
b1.Click += delegate(object sender, EventArgs e) { MessageBox.Show("Clicked"); };
}
But there's even shorter syntax:
public Form1()
{
InitializeComponent();
Button b1 = new Button() { Text = "Button" };
this.Controls.Add(b1);
b1.Click += (sender, e) => MessageBox.Show("Clicked");
}
To break the actual syntax of a lambda down:
(arg1, arg2, ...argN) => { statement1; statement2; ... return statementN; };
The parenthetical section contains the parameter names. You don't provide a type for these parameters; they are automatically typed by the signature of the expected delegate. Note that for a single parameter, the parentheses are optional, and in fact often omitted. For zero or more than one, they are required.
The " => " is actually an operator. You can read it as "goes to."
The {bracketed} section is the method body. It contains standard statements. They may or may not (but often do) make use of the parameters. The previous example did not, the following ones in the article will. Note that for single statements, the brackets are optional and often omitted, as in this example. For multiple statements, they are required. This is similar to ifs and loops.
The return type of the lambda is automatic, just like the parameter types. It is defined by the signature it is supposed to match. In the previous example, its return type is void. In the following example, we will use a lambda that returns a boolean value. If you do use a single statement, and the delegate is not of return type void, the result of the single statement will be returned. If you do use multiple statements and brackets, you must specifically return a value using the return keyword.
So, perhaps a (slightly) more practical example. We have an unsorted list of integers that we need to filter to all values greater than 4. Luckily enough, the System.Linq library includes extension methods for IEnumerables, one of which happens to be Where(). Where() expects a Function as a parameter. Not a function call, but a reference to a function itself (a delegate). Where() will, behind the scenes, loop through each element of the calling IEnumerable, pass each value to the provided function reference, and for each value that returns true, will store it in a new IEnumerable, which it returns when it reaches the end of the caller.
public Form1()
{
InitializeComponent();
int[] list = new int[] { 1, 3, 2, 7, 4, 9, 6, 8, 5 };
int[] result1 = list.Where(IsGreaterThanFour).ToArray();
int[] result2 = list.Where(delegate(int x) { return x > 4; }).ToArray();
int[] result3 = list.Where(x => x > 4).ToArray();
}
private bool IsGreaterThanFour(int x)
{
return x > 4;
}
Again, we see three ways to do the same thing. Each way passes a method reference to the Where method. The first uses a named method, a solution that is pretty unappealing, considering the brevity and lack of need-to-reuse of the code in question. The second uses an anonymous method, and the third uses the lambda shortcut syntax.
Just for fun
In fact, there is a fourth way using the same method, in LINQ:
int[] result4 = (from x in list
where x > 4
select x
).ToArray();
This syntax seems overkill for this example, and it is. But it can be useful for larger queries against object data sources, because of its similarity to SQL and its ease of visual parsing.
You will find the most use for lambdas in your Linq extension methods for IEnumerables, because most of them expect a function reference. Once you understand how the syntax works, these become much easier to write.
Another quick example:
We have a list of strings, and a custom class (MyClass) that holds a string (Value) and an int (Count). We want to create a new List<MyClass> from our List<string>.
public class MyClass
{
public string Value { get; set; }
public int Count { get; set; }
}
public Form1()
{
InitializeComponent();
List<string> list = new List<string>() { "first", "second", "a third string" };
List<MyClass> result = list.Select(x => new MyClass { Value = x, Count = x.Length }).ToList();
}
This lambda takes a string as a parameter, and returns a MyClass. Select() will loop through the calling IEnumerable, and store each returned value in another IEnumerable which it returns when it's done. The lambda we wrote creates a new MyClass from a string and returns the value it creates, which is stored in an IEnumerable, and returned at the end of the Select.
That's all for today, hope this has been enlightening. If you have any questions, let me know.




MultiQuote




|