Let us explore few concepts about Delegates, Anonymous methods,
Lambdas and Expression Trees. This is an introductory post, and I’ll
follow up with more posts. These code examples are pretty simple, you
can fire up a C# Console application in Visual Studio and try these
examples if you are interested.
The above code will give you an output of 50, no doubt, right ? :)
In the above example, note the lambda syntax that replaces the anon method syntax in example 2
The types of input parameters a and b and the
return type will be inferred correctly by the compiler, based on the
context. How ever, on scenarios where the compiler can't infer the type
directly, you can provide that explicitly. Like this.
There are basically two type of lambdas - Statement Lamdas and Expression Lambdas. The above example shows a statement lambda, as the right hand expression is inside a statement block, of the form
If you won't have input parameters, you may use the syntax
=> simply means 'goes to', and you may say that the input parameters goes to the statements (for some processing) :)
We’ve seen how to create Statement lambdas in the above example. Now, let us explore a bit about Expression Lambdas (or single line lambdas). The syntax is similar to statement lambdas, but for expression lambdas, the right hand expression should not be inside a statement block { }. Instead of having statements on the right side, an Expression Lambda can have a single line expression on the right hand side. Here is the simple example, with out the statement block.
The above code produces the same result as in the case of stament
lambdas. How ever, Expression lamdba has an advantage over statement
lambda. When an expression lambda is assigned to a variable of type
Expression, the compiler emits code to build an expression tree that represents the lambda expression, instead of a delegate instance.
In the above example, you saw that we are assigning our expression lambda to the System.Linq.Expression<TDelegate> to create an expression tree, and the compiling it to get the actual delegate. Expression trees provide us a powerful way to represent code/logic as data, that can be modified and/or interpreted at runtime if required.
To provide inline event handlers like
To find items in a collection
For iterating a collection, like
Creating a custom object
Simple one line methods
For aggregate operations
Delegates
We know that a delegate is a type that can reference a method. For example, consider this example to define a delegate and create a delegate instance.- //Example 1 - Creating a delegate instance using Named method
- public delegate int BinaryOperationDelegate(int x,int y);
- class Program
- {
- static void Main(string[] args)
- {
- //Create a delegate instance using named method
- var add = new BinaryOperationDelegate(AddOperation);
- int result = add(20, 30);
- Console.WriteLine(result);
- }
- static int AddOperation(int x,int y)
- {
- return x+y;
- }
- }
Anonymous Methods
Now, you may know that with C# 2.0, we can use anonymous methods to create a delegate instance with out a named method. Let us re-write the above implementation leveraging an anon method. Instead of the method name, you’ve to use the ‘delegate’ keyword. Also, note that there is no need to specify a return type – because the return type will be inferred from the delegate signature.- //Example 2 - Creating a delegate instance using Anon method
- public delegate int BinaryOperationDelegate(int x,int y);
- class Program
- {
- static void Main(string[] args)
- {
- //Create a delegate instance using anon method
- BinaryOperationDelegate add=
- delegate(int a, int b) { return a+b;} ;
- int result = add(20, 30);
- Console.WriteLine(result);
- }
- }
Lambdas
And of course, you might also know that with C# 3.0, you can use Lambdas for producing anonymous methods. A lamda expression is exactly a function, that can contain statements and expressions. Here is the equivalent of above code, still shortened using a lambda- //Example 3 - Creating a delegate instance using statement lambda
- public delegate int BinaryOperationDelegate(int x, int y);
- class Program
- {
- static void Main(string[] args)
- {
- //Create a delegate instance using a statement lambda
- BinaryOperationDelegate add =(a,b)=>{
- //this statement block can contain
- //multiple statements
- return a+b;
- };
- int result = add(20, 30);
- Console.WriteLine(result);
- }
- }
In the above example, note the lambda syntax that replaces the anon method syntax in example 2
- (a,b)=>{
- return a+b;
- };
BinaryOperationDelegate add =(int a, int b)=>{ return a+b; };
There are basically two type of lambdas - Statement Lamdas and Expression Lambdas. The above example shows a statement lambda, as the right hand expression is inside a statement block, of the form
(param1, param2)=> { statement1; statement2; } ;
If you won't have input parameters, you may use the syntax
()=> { statement1; statement2; } ;
=> simply means 'goes to', and you may say that the input parameters goes to the statements (for some processing) :)
Statement Lambdas And Expression Lambdas
We’ve seen how to create Statement lambdas in the above example. Now, let us explore a bit about Expression Lambdas (or single line lambdas). The syntax is similar to statement lambdas, but for expression lambdas, the right hand expression should not be inside a statement block { }. Instead of having statements on the right side, an Expression Lambda can have a single line expression on the right hand side. Here is the simple example, with out the statement block.
- public delegate int BinaryOperationDelegate(int x, int y);
- class Program
- {
- static void Main(string[] args)
- {
- //Expression Lambda
- BinaryOperationDelegate add =(a, b)=>a+b;
- int result = add(20, 30);
- Console.WriteLine(result);
- }
- }
- //Example 4 - Expression Lambdas
- public delegate int BinaryOperationDelegate(int x, int y);
- class Program
- {
- static void Main(string[] args)
- {
- //Expression Lambda to delegate instance
- BinaryOperationDelegate add =(a, b)=>a+b;
- int result1 = add(20, 30);
- //Expression Lambda to Expression tree
- Expression<BinaryOperationDelegate> addExpr = (a, b) => a + b;
- //Let us compile the expression tree before executing the same
- var compiledAdd = addExpr.Compile();
- int result2=compiledAdd(20,30);
- Console.WriteLine(result1);
- Console.WriteLine(result2);
- }
- }
In the above example, you saw that we are assigning our expression lambda to the System.Linq.Expression<TDelegate> to create an expression tree, and the compiling it to get the actual delegate. Expression trees provide us a powerful way to represent code/logic as data, that can be modified and/or interpreted at runtime if required.
Example Usages for Lambdas
These are some of the areas you may find using Lambdas pretty often.To provide inline event handlers like
- button.Click += (sender,args) =>
- {
- };
- var dogs= animals.Where(animal => animal.Type == "dog");
- animals.ForEach(animal=>Console.WriteLine(animal.Name));
- var myObj= mySource.Select(x => new {Name = x.name, Age= x.age});
- Func<int, int> add = x => x + x;
- double charCount = document.Sum(word => word.Length)
No comments :
Post a Comment