Widely asked in interviews: Delegate, Linq, Lambda Expn Create Extension Method & Expression Tree


In technical interviews most of the times, TRICKY questions are fired on topics; Delegate, Anonymous Method, Anonymous Type, LINQ, Extension Method, Lambda Exp, Expression Tree..... Though most of us know these concepts but get messed-up and unable to explain in interviews as required..... This article covers these topics with Code-Snippets that others can refer to understand the topics.

We will Start with 'Delegate' and will complete the article with 'Writing your own Custom Extension methods'



## Delegate:

Delegate in C# is a way to pass function as parameter along with parameters without let the developer know where the actual function resides.
Developer just need to call the delegate object with the function's parameters.

Delegate has following features:

1. Functions can be passed in its constructor
2. Parameters can be pass to those functions
3. Can be used as callback methods (this feature is out of scope of this Article, hence I have not included in code-snippets)
4. Does not require name

Sample Code

      // Delegate with named function
      public class Approach1
      {
            // 1. Declare function
            public string MyFunction(string name, string department, decimal experience)
            {
                  StringBuilder sb = new StringBuilder();
                  sb.AppendLine("Employee Name: " + name);
                  sb.AppendLine("Department Name: " + department);
                  sb.AppendLine("Experience: " + experience.ToString() + " years");
                  return sb.ToString();
            }

            public delegate string MyDelegate(string name, string department, decimal experience);

            // Test method
            public void Test()
            {
                  // 3. Instentiate delegate
                  MyDelegate myDelegate = new MyDelegate(MyFunction);
                  String n = "Some Name";
                  String d = "Some Department";
                  decimal e = 5.2M;

                  // 4. Call the function
                  string Detail = myDelegate(n, d, e);
                  Console.WriteLine("Approach - 1 (delegate with named function)");
                  Console.WriteLine("Employee Detail ...");
                  Console.WriteLine(Detail);
                  Console.ReadKey();
            }
      }


## Anonymous Method:

An Anonymous Method is a method body scopped with { ..... } which can be defined with a delegate().

Anonymous method has following features:

1. Can be define inline
2. Does not require name
3. Does not require parameter
4. Does not require to return a value
5. Eliminates declaration of delegate

Sample Code

      // Delegate WITH anonymous method and parameter passing
      public class Approach2
      {
            // 1. Declare delegate
            public delegate string MyDelegate(string name, string department, decimal experience);

            public void Test()
            {
                  // 2. Instentiate delegate with anonymous method (and parameters)
                  MyDelegate myDelegate = delegate(string name, string department, decimal experience)
                                               {
                                                      StringBuilder sb = new StringBuilder();
                                                      sb.AppendLine("Employee Name: " + name);
                                                      sb.AppendLine("Department Name: " + department);
                                                      sb.AppendLine("Experience: " + experience.ToString() + " years");
                                                      return sb.ToString();
                                               };

                  String n = "Some Name";
                  String d = "Some Department";
                  decimal e = 5.2M;

                  // 3. Call the function
                  string Detail = myDelegate(n, d, e);
                  Console.WriteLine("Approach - 2 (delegate WITH anonymous method and parameter passing)");
                  Console.WriteLine("Employee Detail ...");
                  Console.WriteLine(Detail);
                  Console.ReadKey();
            }
      }


Another Example:


      // Delegate WITH anonymous method ( WITHOUT parameter passing )
      public class Approach3
      {
            // 1. Declare delegate
            public delegate string MyDelegate();

            public void Test()
            {
                  String n = "Some Name";
                  String d = "Some Department";
                  decimal e = 5.2M;

                  // 2. Instentiate delegate with anonymous method (without parameters)
                  MyDelegate myDelegate = delegate()
                  {
                        StringBuilder sb = new StringBuilder();
                        sb.AppendLine("Employee Name: " + n);
                        sb.AppendLine("Department Name: " + d);
                        sb.AppendLine("Experience: " + e.ToString() + " years");
                        return sb.ToString();
                  };

                  // 3. Call the function
                  string Detail = myDelegate();
                  Console.WriteLine("Approach - 3 (delegate WITH anonymous method and WITHOUT parameter passing)");
                  Console.WriteLine("Employee Detail ...");
                  Console.WriteLine(Detail);
                  Console.ReadKey();
            }
      }


## Anonymous Type:

An Anonymous Type is a way that lets the developer bundle a set of properties (of various types) in one object whose type is unknown at design-time/run-time.
This approach gives us a flexibility to create a complex object, collection or a combonation of both.

Rules for Anonymous Types:

1. Internally these types are derived from System.Object class
2. To access properties of object of type 'Anonymous Types' which is boxed as Object type, we need to Cast back with dynamic as follow:

Right Approach:

     var v = new { e = 3, n = "Sharad" };
     Object o = v; // boxed
     int experience = ((dynamic)o).e;
     string name = ((dynamic)o).n;

Right:

     var v = new { e = 3, n = "Sharad" };
     Object o = v as Object;
     dynamic d = o;
     int experience = d.e;
     string name = d.n;

Wrong Approach:

     Object o = new { e = 3, n = "Sharad" };
     var v = o;
     int experience = v.e;
     string name = v.n;

1. In the same way if we want to pass Anonymous Type objects to some method as parameter, we need to receive them as 'dynamic' or 'object' as follows:

            public void Test()
            {
                 .....
                 var v = new { e = 3, n = "Sharad" };
                 TestFunction(v);
                 .....
            }

            public void TestFunction(dynamic d)
            {
                .....
                int experience = d.e;
                string name = d.n;
                .....
            }

2. Properties of such objects remain read-only
3. These Types cannot be used as Property types or Method's return types

## Linq:

Linq stands for "Language Integrated Query". DotNet Linq facilitates an approach for general-purpose query building and executing with the standard SQL flavore.

Ling provides various features to the developers like:

1. Queries can be built on metadata available to the application
2. Verify design/compile time syntax
3. Intellisense with the objects and properties
4. Process information from datasources like; tables, objects, xml etc
5. Standard sql features are available like; filtering, projection, joins, grouping, ordering etc
6. Can be applied to all the objects that implement IEnumerable

In it's most simplest form, a Linq query can be written as follows:

IEnumerable<string> invalidNames = from n in EmployeeNameCollection where n.Length<2 order by n select n

Syntax:

IEnumerable<anyType> list = from <alias> in <IEnumerable collection> where <expression based on alias> order by <alias.properties, ...> select <alias>....;

Sample Code:

      // Linq with Anonymous Type
      public class Approach4
      {
            public class Employee
            {
                  public Employee(String Name, String Department, Decimal Experience)
                  {
                        this.Name = Name;
                        this.Department = Department;
                        this.Experience = Experience;
                  }
                  public string Name { get; set; }
                  public string Department { get; set; }
                  public decimal Experience { get; set; }
            }

            public void Test()
            {
             List<Employee> Employees = new List<Employee>(){new Employee("Ram","Sales",5.5M),new Employee("Ajay","HR",3.5M),new Employee("Joy","IT",4.5M)};

             // 1. Linq Query with Extension Method (result will be of Anonymous Type)
             var detailInfo = (from n in Employees
             where n.Experience > 4
             select new {detail = String.Format("Employee Name:{0}\nDepartment Name:{1}\nExperience:{2} years\n",n.Name,n.Department,n.Experience.ToString())}
             ).First();

             // 2. Accessing property (detail) from the object (detailInfo) of Anonymous Type
             string detail = detailInfo.detail;

             Console.WriteLine("Approach - 4 (Linq, Anonymous Type)");
             Console.WriteLine("Employee Detail ...");
             Console.WriteLine(detail);
             Console.ReadKey();
            }
      }


## Built-in Extension methods:

Query given in above code-snippet can also be written with built-in method expressions as follows:

IEnumerable<string> invalidNames = EmployeeNameCollection.Where( n => n.Length<2 ).OrderBy( n => n).Select( n => n);

Here the methods Where(.=>.), OrderBy(.=>.), Select(.=>.) are Built-in Extension Methods of Linq.

We can also create our own Custom Extension Methods for Custom Types (like List<Employee>)... (Extension Methods are explained later in this article)

Some of the Built-in Extension Methods are:

1. Distinct(): To return distinct set of records from a collection:

Sample Code:

        public class MyClass
        {
                public int c { get; set; }
                public string n { get; set; }
        }

        public class MyEquality : IEqualityComparer<MyClass>
        {
                private static int i;

                static MyEquality()
                {
                        i = 1;
                }

                public bool Equals(MyClass o1, MyClass o2)
                {
                        return o1.c.Equals(o2.c) && o1.n.Equals(o2.n);
                }

                public int GetHashCode(MyClass o)
                {
                        return o.c.GetHashCode();
                }
        }

        static void Main(string[] args)
        {
                List<MyClass> list = new List<MyClass>() {
                new MyClass{ c = 1, n = "Raj" },
                        new MyClass{ c = 4, n = "Ajay" },
                        new MyClass{ c = 2, n = "Pol" },
                        new MyClass{ c = 2, n = "Pol" },
                        new MyClass{ c = 20, n = "Pol" },
                        new MyClass{ c = 20, n = "Nik" },
                        new MyClass{ c = 4, n = "Sam" },
                        new MyClass{ c = 3, n = "Viki" }
                };

IEqualityComparer<MyClass> me = new MyEquality();

                var v = list.Distinct(me); // o/p {1,"Raj"}, {4, "Ajay"}, {2, "Pol"}, {20, "Pol"}, {20, "Nik"}, {4, "Sam"}, {3, "Viki"}
        }

2. Where(): To apply a where criteris on collection:

Sample Code:

        List<int> list = new List<int>() { 1, 2, 3, 3, 4, 5, 5, 6, 6, 7, 8, 9, 10 };
        var v2 = list.Where(n => n % 2 == 0); // o/p 2,4,6,6,8,10


3. Select(): It projects on the current record/entity from comming sequence and allows us to process specific property of that record/entity. { The Select method actualy execute the Linq query }

Sample Code:

        List<int> list = new List<int>() { 1, 2, 3, 3, 4, 5, 5, 6, 6, 7, 8, 9, 10 };
        var v3 = list.Select(n => (n % 2 == 0 ? "Even" : "Odd") + " Number"); // o/p Even, Odd, Odd, Even, Odd, Odd, Even, Even, Odd, Even, Odd, Even


4. OrderBy(), OrderByDescending(): To define the Order of returned records as Ascending, Descending.

Sample Code:

        List<int> list = new List<int>() { 1, 2, 3, 3, 4, 5, 5, 6, 6, 7, 8, 9, 10 };
        var v4 = list.OrderBy(n => n); // o/p 1, 2, 3, 3, 4, 5, 5, 6, 6, 7, 8, 9, 10
        var v5 = list.OrderByDescending(n => n); // o/p 10, 9, 8, 7, 6, 6, 5, 5, 4, 3, 3, 2, 1


5. GroupBy(): To return a collection based on grouping on desired properties.

Sample Code:


// Example Due


             
6. Join(): To join collections and returns the resultant as a new collection:

Sample Code:

        public class Employee
        {
                public int eCode { get; set; }
                public string eName { get; set; }
                public int dCode { get; set; }
        }

        public class Designation
        {
                public int dCode { get; set; }
                public string dName { get; set; }
        }

        static void Main(string[] args)
        {

                List<Employee> employees = new List<Employee>() {
                                new Employee{ eCode = 1, eName = "Raj", dCode = 1 },
                                new Employee{ eCode = 4, eName = "Ajay", dCode = 3 },
                                new Employee{ eCode = 2, eName = "Pol", dCode = 2},
                                new Employee{ eCode = 20, eName = "Nik", dCode = 3},
                                new Employee{ eCode = 3, eName = "Viki", dCode = 3}
                };

                List<Designation> departments = new List<Designation>() {
                                new Designation{ dCode=1, dName="Architech" },
                                new Designation{ dCode=2, dName="Lead" },
                                new Designation{ dCode=3, dName="Developer" },
                };

                var employeeDetail = employees.Join( departments, e => e.dCode, d => d.dCode, (e,d) => new { e.eCode, e.eName, e.dCode, d.dName} );
        }


7. Intersect(): To find intersection of collections and returns the resultant as a new collection:

Sample Code:

        List<String> employees1 = new List<String>() { "Raj", "Ajay" , "Pol"};
        List<String> employees2 = new List<String>() { "Pol", "Raj", "Nik" };
        var v = employees1.Intersect(employees2); // o/p "Raj", "Pol"


8. Concat(): To Concatinate one collection to another and returns the resultant as a new collection:

Sample Code:

        List<String> employees1 = new List<String>() { "Raj", "Ajay" , "Pol"};
        List<String> employees2 = new List<String>() { "Pol", "Raj", "Nik" };
        var v = employees1.Concat(employees2); // o/p "Raj", "Ajay" , "Pol","Pol", "Raj", "Nik"


9. Contains(): To verify whether a collection contains some member .. It returns boolean

Sample Code:

        List<String> employees1 = new List<String>() { "Raj", "Ajay" , "Pol", "Nik" };
        var v = employees1.Contains("Pol"); // o/p true

             
10. First(): To return First record of source collection:

Sample Code:

        List<String> employees1 = new List<String>() { "Raj", "Ajay" , "Pol", "Nik" };
        var v = employees1.First(); // o/p "Raj"

             
11. Count(), Sum(), Average(), Max(), Min(): To return results of various Aggregate functions.

Sample Code:

        List<double> salaries = new List<double>() { 10000, 20000, 45000, 43000, 12345, 43234 };
        var count = salaries.Count(); // o/p 6
        var sum = salaries.Sum(); // o/p 173579.0
        var average = salaries.Average(); // o/p 28929.833333333332
        var max = salaries.Max(); // o/p 45000.0
        var min = salaries.Min(); // o/p 10000.0

             
## Lambda Expression:

In above queries the Expression Arguments passed to the Extension methods are called "Lambda Expressions",

Which consist of 3 parts :

1. Left-part: Parameters for execulable part
2. Goes-to-operator: Symbol '=>'
3. Right-part: Executable part

And, the code fregment ' n.Length < 2 ' is similar to anonymous method.

Hence, a Lambda Expression can be defined as an Anonymous method/function that can be passed as a parameter to Extension Methods.

SampleCode:

      // Lambda Expression
      public class Approach5
      {
            public class Employee
            {
                  public Employee(String Name, String Department, Decimal Experience)
                  {
                        this.Name = Name;
                        this.Department = Department;
                        this.Experience = Experience;
                  }
                  public string Name { get; set; }
                  public string Department { get; set; }
                  public decimal Experience { get; set; }
            }

            public void Test()
            {
                  List<Employee> Employees = new List<Employee>() { new Employee("Harish", "Sales", 5.5M), new Employee("Aakash", "Excise", 3.5M), new Employee("Mahesh", "IT", 4.5M) };

                  // 1. Lambda Expression
                  string Detail = Employees.Where(n => n.Experience > 4).Select(n =>
                  {
                        StringBuilder sb = new StringBuilder();
                        sb.AppendLine("Employee Name: " + n.Name);
                        sb.AppendLine("Department Name: " + n.Department);
                        sb.AppendLine("Experience: " + n.Experience.ToString() + " years");
                        return sb.ToString();
                  }).First();

                  Console.WriteLine("Approach - 5 (Lambda Expression)");
                  Console.WriteLine("Employee Detail ...");
                  Console.WriteLine(Detail);
                  Console.ReadKey();
            }
      }


## Expression Tree:

Expression tree feature allows developer to build custom LINQ queries at run-time.

These custom queries are useful when developer does not know in design-time, that what internals would be there in the lambda expressions.

Internally these trees works with queries that need IQueryable data so that the LINQ query engine can traverse the tree to convert it into a query language, compatible to desired datatype.

Steps to create and use Expression tree:

0. Consider complete syntax of Lambda Expression: parameter-part => execution-part
1. Create "parameter-part" as ParameterExpression type.
2. Create Expression tree statement as Expression< Func< ClassType, DataType > > type.
3. The tree is created with ParameterExpression and PropertyName.
4. 'Func< ClassType, DataType >' is Generic Delegate to which we pass 2 parameters; ClassType and the return DataType.
5. Call AsQueryable() method of collection which returns 'object' that implements IQueryable & IEnumerable interfaces.
6. Call any Extension method of this 'object' and pass Expression Tree statement to it to get desired result.

(Refer following Code snippet)

Consider, we have a collection of objects of Employee class type:

SampleCode:

       public class Employee
       {
               public int Code { get; set; }
               public string Name { get; set; }
               public decimal AspNetExp { get; set; }
               public decimal DatabaseExp { get; set; }
       }

       public class SomeLibrary
       {
              public static Expression<Func<Employee, decimal>> CreateExpression(string propertyName)
              {
                     var parameterExpression = Expression.Parameter(typeof(Employee));
                     var expression = Expression.Lambda<Func<Employee, decimal>>(Expression.Property(parameterExpression, propertyName), parameterExpression);
                     return expression;
              }

              // Other helper methods
              // ...
              // ...
       }

       static void Main(string[] args)
       {
              List<Employee> employees = new List<Employee>() {
                     new Employee{ Code = 1, Name = "Raj", AspNetExp = 1.4M, DatabaseExp=1.2M },
                     new Employee{ Code = 4, Name = "Ajay", AspNetExp = 2.5M, DatabaseExp=2.8M },
                     new Employee{ Code = 2, Name = "Pol", AspNetExp = 5.1M, DatabaseExp=5.3M },
                     new Employee{ Code = 20, Name = "Nik", AspNetExp = 4.0M, DatabaseExp=5.1M },
                     new Employee{ Code = 3, Name = "Viki", AspNetExp = 3.6M, DatabaseExp=2.8M }
              };

              var v1 = employees.AsQueryable().Select<Employee, decimal>(Library.CreateExpression("AspNetExp"));
              var v2 = employees.AsQueryable().Select<Employee, decimal>(Library.CreateExpression("DatabaseExp"));           
       } 
       


Where:

1). We are passing "AspNetExp" & "DatabaseExp" to the CreaterBuilder helper method.
2). This helper method will be pushed into Expression.Lambda() Factory Method.
3). This factory method defines the internals for our LINQ query at run-time.
4). This gives flexibility to decide at run-time, that which property of all sequence should reflect as result.

## Writing your Own Custom Extension Methods:

Extension Methods give the developer flexibility to extens a Base type or Custom type without modifying/recompile them.

Once created these methods can be called just like normal methods available in that type.

Steps to create Extension Methods:>

1. Create static class (eg. MyExtensionMethodLibrary) in SAME namespace.
2. Create static method in this class which:
   (i) Receives first parameter with 'this' keyword. The parameter type should be same as the SourceType for which we are creating Extension method.
   (ii) Returns the desired type (optional).
3. Once created, the same method will be available with all objects of Same Type.
4. In our sample code following Extension Method works with 'Employee class' and 'return type as decimal'.

SampleCode:

       // I have restructured "Expression Tree" POC to meet requirements for "Extension Methods"
       namespace Approaches
       {
              public class Employee
              {
                     public int Code { get; set; }
                     public string Name { get; set; }
                     public decimal AspNetExp { get; set; }
                     public decimal DatabaseExp { get; set; }
              }

              public class Library
              {
                     public static Expression<Func<Employee, decimal>> CreateExpression(string propertyName)
                     {
                            var parameterExpression = Expression.Parameter(typeof(Employee));
                            var expression = Expression.Lambda<Func<Employee, decimal>>(Expression.Property(parameterExpression, propertyName), parameterExpression);
                            return expression;
                     }
              }

              public static class MyExtensionMethodLibrary
              {
                     public static IQueryable FetchRecords(this List<Employee> sourceList, string propertyName)
                     {
                            IQueryable result = sourceList.AsQueryable().Select<Employee, decimal>(Library.CreateExpression(propertyName));
                            return result;
                     }
              }

              class Program
              {
                     public void TestExtensionMethod()
                     {
                            List<Employee> employees = new List<Employee>() {
                            new Employee{ Code = 1, Name = "Raj", AspNetExp = 1.4M, DatabaseExp=1.2M },
                            new Employee{ Code = 4, Name = "Ajay", AspNetExp = 2.5M, DatabaseExp=2.8M },
                            new Employee{ Code = 2, Name = "Pol", AspNetExp = 5.1M, DatabaseExp=5.3M },
                            new Employee{ Code = 20, Name = "Nik", AspNetExp = 4.0M, DatabaseExp=5.1M },
                            new Employee{ Code = 3, Name = "Viki", AspNetExp = 3.6M, DatabaseExp=2.8M }
                     };

                     var v1 = employees.FetchRecords("AspNetExp");
                     var v2 = employees.FetchRecords(DatabaseNetExp");
              }
       }


I hope all the topics are coveded properly along with example.

Samples available in this resource are written as per my understanding. To report a technical issue or suggestion / query,
please do post it.

Thanks!


Comments

Author: keyur soni10 Oct 2012 Member Level: Silver   Points : 0

Hi,

Very helpful question.
Thanks for share

Author: Thaniya13 Nov 2012 Member Level: Silver   Points : 0

Hi,

Thanks for your sharing detailed description of the Delegate, LINQ and LAMDA expression

Thanks

Guest Author: navas15 Nov 2012

Rally useful. thank u so much

Guest Author: Ajit Kumar Das15 Nov 2012

Thanks For Very useful share........

Author: Vivek Nair27 Jan 2013 Member Level: Bronze   Points : 0

Very Useful resource. The detailing is in very simple language and helps reader grasp the crux quickly.

Author: Pawan Awasthi01 Jun 2013 Member Level: Gold   Points : 2

Hai SSharma,
Good collection of the interview questions. These are really the good topics where now a days companies are concentrating more in the technical interview panels.
These topics will really be helpful for the people who are looking out for job and having 3+ yrs of experience.
Thanks for sharing these topics.

Author: Nandraj05 Jul 2013 Member Level: Bronze   Points : 0

thanks for valuable information for interview..

Author: Anil kushawaha13 Sep 2014 Member Level: Silver   Points : 0

thanx for nyc information

Author: Devil Aaj02 May 2016 Member Level: Bronze   Points : 4

For Free Query Visit:-
Packers and Movers in Delhi @ http://www.shiftingexpert.in/packers-and-movers-delhi.html
Movers and Packers Bangalore @ http://www.shiftingexpert.in/packers-and-movers-bangalore.html
Movers and Packers Hyderabad @ http://www.shiftingexpert.in/packers-and-movers-hyderabad.html
Movers and Packers Pune @ http://www.shiftingexpert.in/packers-and-movers-pune.html
Movers and Packers Mumbai @ http://www.shiftingexpert.in/packers-and-movers-mumbai.html
Movers and Packers Gurgaon @ http://www.shiftingexpert.in/packers-and-movers-gurgaon.html



  • Do not include your name, "with regards" etc in the comment. Write detailed comment, relevant to the topic.
  • No HTML formatting and links to other web sites are allowed.
  • This is a strictly moderated site. Absolutely no spam allowed.
  • Name:
    Email: