Advanced Features In C#

Introduction

 
In this article, we will be discussing some advanced features of C# such as anonymous methods and lambda expressions. Anonymous methods are methods without any name. A lambda expression is basically an anonymous function, just more optimized. 
 

Anonymous methods

 
Anonymous methods are the basis for lambda expressions. Prior to C# version 2.0, the only method to declare a delegate was to use name methods. A delegate could not be pointing to a method that does not have a name. It had to point to some method that has a name.
 
C# 2.0 introduced the concept of anonymous methods. In C# 3.0, anonymous methods got upgraded to Lambda expressions. Anonymous methods allow delegates to point to something that is not there that is a nameless function.
 
If there are functions to be called by delegates, then there is no need of such functions. We can simply write an inline method as either an anonymous method or lambda expression using the keyword delegate. These functions do not have any names. Anonymous methods enable us to omit parameter list. Anonymous methods can be converted to delegates with a huge variety of signatures.
 
Let's declare a delegate, so that we can see how it looks in both cases; that is, when using it with a normal function as well as with an anonymous method.
 
Using delegate with a standard function
  1. using System;  
  2.   
  3. namespace Anonymous  
  4. {  
  5.     class Program  
  6.     {  
  7.         delegate void CountNumbers();  
  8.         static void Main(string[] args)  
  9.         {  
  10.             CountNumbers countNumberDel = Count;  
  11.             countNumberDel();  
  12.         }  
  13.   
  14.         static void Count()  
  15.         {  
  16.             for(int i=0;i<5;i++)  
  17.             {  
  18.                 Console.WriteLine(i);  
  19.             }  
  20.         }  
  21.     }  
  22. }  
Here we are creating a delegate of return type void. Inside the main() function we are creating an instance of CountNumbers delegate named countNumberDel. The instance of CountNumbers delegate is pointing to the Count function. The instance will display the required output of logic defined inside Count function. After creating the Count function, the instance of CountNumbers delegate named countNumberDel will point to the Count function, as both the delegate and function contains the exact number of parameter values.
 
Output
 
Advanced Features In C#
 
Using delegate as an anonymous method 
  1. using System;  
  2.   
  3. namespace Anonymous {  
  4.   
  5.     class Program {  
  6.   
  7.         delegate int TotalIt(int x);  
  8.         static void Main(string[] args) {  
  9.             TotalIt total = delegate(int x) // we will use it like a function  
  10.             {  
  11.                 int tot = 0;  
  12.                 for (int i = 0; i < x; i++)  
  13.                 tot += i;  
  14.                 return tot;  
  15.             };  
  16.             Console.WriteLine(total(10));  
  17.         }  
  18.   
  19.     }  
  20. }  
Here we are creating a delegate of int type. Inside the main() function we are creating an instance of TotalIt delegate named total. Instead of making the instance point to any function, we are creating an anonymous function with delegate keyword and passing the exact number of parameters as an original delegate contains. Inside the body of anonymous function, we can write our own logic.
 
After creating the anonymous function, we can call that function using delegate instance and passing the exact number of parameter values as an original delegate contains.
 
Output
 
Advanced Features In C#
 

Lambda expressions

 
Lambda expressions were created to replace anonymous methods. They are much more flexible and effective than anonymous methods as we can perform a lot more tasks with lambda expressions in comparison to anonymous methods . They are shorter and quicker to use.
 
A lambda expression is basically an anonymous function, just more optimized. By using lambda expressions, we can write local functions that can be passed as arguments and returned as a value of function calls. They are particularly helpful for writing the LINQ query.
 
The lambda expression can be denoted using => that is, equal to greater than sign. This sign signifies ‘goes to’ statement to verbalize this operator.
 
There are three different types of lambdas--  expression lambdas, statement lambdas and async lambdas.

Expression lambda
 
An expression lambda is a lambda expression with an expression on the right side of an operator. For example, below is a syntax of expression lambda with just one line of expression.
 
(input parameter)=>{statement;}
 
Below is the code snippet for expression lambda:
  1. using System;  
  2.   
  3. namespace LambdaExpression  
  4. {  
  5.     class Program  
  6.     {  
  7.         delegate int CountIt(int x);  
  8.         static void Main(string[] args)  
  9.          {  
  10.             #region expression lambda  
  11.             CountIt expressionLambdaDel = (int x) => x + 5;  //here delegate is used like a function.
  12.             Console.WriteLine(expressionLambdaDel(5));               
  13.                                                         
  14.             #endregion  
  15.               
  16.          }  
  17.     }  
  18. }  
Here we are defining a delegate named CountIt which has a return type of int and contains a single parameter. Inside the main function, we are creating an instance of the delegate as follows:
 
CountIt expressionlambda = (int x)=>x+5;
 
Here, x goes to the expression, 5 is added to it and the value is returned. This lambda expression takes care of taking the parameter from the delegate, adding 5 to it and then returning it. The return value is automatically cast in by the delegate. The compiler knows that delegate has a return type of int.
 
expressionlambda(5);
 
Here we are calling the delegate instance and passing 5 to it. This is the same as pointing delegate to some function. Here we are creating an expression for the delegate and then calling the delegate but there is no need to create a function here.
 
Output
 
Advanced Features In C#
 
Statement lambda
 
A statement lambda resembles an expression lambda except that statements are enclosed within parenthesis.
 
Statement lambda can have a whole function body inside it.
  1. using System;  
  2.   
  3. namespace LambdaExpression {  
  4.     class Program {  
  5.         delegate int CountIt(int x);  
  6.         delegate void StandardDelegate();  
  7.         static void Main(string[] args) {  
  8.  
  9.             #region statement lambda  
  10.             CountIt statementLambdaDel = (int x) = > // we can use it as a function body  
  11.             {  
  12.                 int sum = 0;  
  13.                 for (int i = 0; i < x; i++)  
  14.                 sum += i;  
  15.                 return sum;  
  16.             };  
  17.             Console.WriteLine(statementLambdaDel(5));  
  18.             Console.WriteLine(statementLambdaDel(5));#endregion  
  19.         }  
  20.     }  
  21. }  
it needs to have return statement here, otherwise it won’t let you compile the code. With statement lambda we lose the liberty of not supplying the return value.
 
Console.WriteLine(statementlambda(5));
 
Output 
 
Advanced Features In C#
 
Let's take another example where we will be using C# Lists. We can use lambda expressions with list as well. We will be using a function called FindIndex() which is defined inside list class.
  1. using System;  
  2. using System.Collections.Generic;  
  3.   
  4. namespace LambdaExpression  
  5. {  
  6.     class Program  
  7.     {  
  8.           
  9.         List<int> numberTable = new List<int> { 10, 20, 21, 30, 40 };  
  10.   
  11.         Console.WriteLine(numberTable.FindIndex(x => x % 2 != 0));  
  12.   
  13.     }  
  14. }  
Output
 
Advanced Features In C#
 
Here we have created a list named numberTable with the following elements in it: 10,20,21,30,40.
 
We are looping through every single element and returning an index of that number which is not an even number.
 
So this is how lambda expressions are mostly used as predicate methods.
 

Summary

 
In this article, we have discussed anonymous functions and lambda expressions in detail. We have demostrated each and every concept with a proper code example.