The origins of the term Lambda Expression can be traced to an American mathematician Alonzo Church. He published a paper in 1936 that introduced Lambda Calculus.
Lambda Calculus is used to investigate:
- function definition
- function application (implementation)
- recursion
Lambda Calculus was influential in the design of LISP and eventually all functional programming languages.
You can find more info on LISP here.
The key capability of a lambda expression is that it provides a concise natural way to pass a code block as a parameter.
In C#, a lambda expression is implemented as an anonymous method.
Before we go further it is important to know about delegates.
A delegate is a data structure that refers to one or more methods, and for instance methods, it also refers to the corresponding object instance. The closest equivalent of a delegate in C/C++ is a function pointer. However, a C/C++ function pointer can only reference static functions. A delegate can reference both static and instance methods.
Simple C# Delegate Example: (20 lines of code)
using System;
class DelegateTest
{
delegate void DelegateType(); // delegate method declaration
static DelegateType GetMethod()
{
return new DelegateType(MethodBody);
}
static void MethodBody() // method definition
{
Console.WriteLine("Hello");
}
static void Main()
{
DelegateType delegateInstance = GetMethod();
delegateInstance(); // invokes method
delegateInstance(); // invokes method again
Console.ReadKey();
}
}
C# 2.0 introduces anonymous methods, which allow code blocks to be written ‘inline’ where delegate values are expected.
using System;
class Program
{
delegate void DelegateType(); // delegate method declaration
static DelegateType GetMethod()
{
return delegate() { Console.WriteLine("Hello");};
// anonymous method
}
static void Main()
{
DelegateType delegateInstance = GetMethod();
delegateInstance(); // invokes method
delegateInstance(); // invokes method again
Console.ReadKey();
}
}
Example of Anonymous Method with two parameters.
using System;
class Program
{
// delegate method declaration
delegate void DelegateType(string name, int val);
static DelegateType GetMethod()
{
// anonymous method with parameters
return delegate(string name, int val)
{ Console.WriteLine(
"Hello name:{0} - value:{1}", name, val
);};
}
static void Main()
{
DelegateType delegateInstance = GetMethod();
delegateInstance("Henry David Thoreau", 44);
// invokes method
delegateInstance("Sandra Day O’Connor", 23);
// invokes method again
Console.ReadKey();
}
}
The Anonymous Method feature is unique to C#. Don Box refers to it as closure.
Java’s equivalent is inner classes and anonymous inner classes.
Java Anonymous Inner Class Example
public class MyClass extends Applet
{
...
someObject.addMouseListener(new MouseAdapter()
{ // anonymous class definition and
// instantiation here
public void mouseClicked(MouseEvent e)
{
...//Event listener code here...
}
} );
...
}
C# Lambda Expression
C# 3.0 introduces lambda expressions, to provide a more concise way to write anonymous methods.
To illustrate, let’s see an anonymous method sample and then compare it to a lambda expression version.
Another C# Anonymous Method Example
class Lambda
{
static void TestLambdaExpression()
{
List list = new List();
list.Add(1);
list.Add(2);
list.Add(3);
list.Add(4);
// FindAll() calls an anonymous method
List evenNumbers =
list.FindAll(delegate(int i) { return (i % 2) == 0; } );
foreach (int evenNumber in evenNumbers)
{
Console.WriteLine(evenNumber);
}
}
static void Main(string[] args)
{
TestLambdaExpression();
}
}
C# Lambda Expression Example
class Lambda
{
static void TestLambdaExpression()
{
var list = new List();
list.Add(1);
list.Add(2);
list.Add(3);
list.Add(4);
// FindAll() contains a Lambda Expression =>
var evenNumbers = list.FindAll(i => (i % 2) == 0);
foreach (int evenNumber in evenNumbers)
{
Console.WriteLine(evenNumber);
}
}
static void Main(string[] args)
{
TestLambdaExpression();
}
}
So we see that a lambda expression is written as a parameter list, followed by the => token, followed by an expression.
Examples:
(int x) => x + 1 // parameter list, expression
(int i) => (i % 2) == 0 // parameter list, expression
Please note that the parameter list can be explicitly typed or implicitly typed.
For an implicitly typed parameter list, the parameter type is inferred from the context in which the lambda expression is used. Also, if a lambda expression has a single, implicitly typed parameter, then the parentheses can be omitted. So this works too.
x => x + 1 // parameter list, expression
i => (i % 2) == 0 // parameter list, expression
Here is a case with multiple parameters:
(x,y) => return x * y; // parameter list, expression
Well that’s enough intro to Lambda Expressions.
I will follow up with a part 2 to show Expression Trees and how LINQ uses it to pass code as parameters.
If interested in LISP, you can find examples of LISP Lambda Expressions here.
40.740830
-73.998518