in

Foo Theory

Partners in Community - serving up some ice cold Kool-Aid!
Welcome to footheory.com.  The bloggers and contributing members on this site are consultants, project/program managers and software architects working across the US.  Our community will focus on Microsoft technologies, .NET architecture, software patterns & practices and just plain stream of consciousness.

Bennie's Weblog

August 2007 - Posts

  • New Features in C# 3.0, Part 6: Expression Trees

    Introduction

    In the previous installment of this series, we looked at lambda expressions. During our little trip down memory lane, we concluded that lambda expressions are a logical evolution of anonymous functions, which in turn are (to some extent) an evolution of delegates. In the context of this article, it is very important to understand that lambda expressions are always directly compiled into IL code by the compiler, so a lambda expression is a representation of a unit of executable code, it is not a data structure.

    Below is an example of a lambda expression that calculates the volume of a box:

    Func<double, double, double, double> boxVolume = (width, length, height) => width * length * height;

    Next, let's take a look at this line of code:

    Expression<Func<double, double, double, double>> volumeExpr = (width, height, length) => m_width * m_height * m_length;

    Essential, what we are doing in this line of code is taking our earlier lambda expression, and supplying it as the type argument for a generic type called Expression<T>. Expression<T> is defined in the System.Linq.Expressions namespace, and looks as follows:

    1 // Summary: 2 // Represents a strongly typed lambda expression as a data structure in the 3 // form of an expression tree. This class cannot be inherited. 4 // 5 // Type parameters: 6 // TDelegate: 7 // The type of the delegate that the System.Linq.Expressions.Expression<TDelegate> 8 // represents. 9 public sealed class Expression<TDelegate> : LambdaExpression 10 { 11 // Summary: 12 // Compiles the lambda expression described by the expression tree into executable 13 // code. 14 // 15 // Returns: 16 // A delegate of type TDelegate that represents the lambda expression described 17 // by the System.Linq.Expressions.Expression<TDelegate>. 18 public TDelegate Compile(); 19 } 20

    When you look at the comments for the class, you notice that an Expression<T> represents a lambda expression as a data structure in the form of an expression tree. So, rather than directly compiling the lambda expression into executable IL that can directly evaluate the expression, what an Expression<T> does is create an in-memory tree of objects that represents the expression that was supplied as its type argument.

    Now, when you look at the definition of Expression<T> you probably noticed it single method called Compile(). This method compiles the expression, and when the compilation is successful,  generates the "real" lambda expression, which then in turn can be executed, because it really IS IL, ready to run! To execute a compiled Expression<T> instance, just use it's Invoke() method, supplying the required parameters.

    An overview of this two-step process is shown below:

    ExpressionTreesOverview

    The in-memory representation of an Expression<T> is an expression tree, as is shown in the above figure.

    Microsoft actually made a visualizer available, which is very useful for analyzing the structure of an expression tree. A screen shot of the visualizer for our expression looks as follows:

    ss

    Getting the Expression Tree Visualizer up and running in Orcas Beta 2

    In Beta 2 of Orcas, the expression tree visualizer is NOT installed by default. But fear not, and follow these steps to get the visualizer to work:

    • If you are running the Orcas Beta 2 VPC image, go to the directory: C:\Program Files\Microsoft Visual Studio 9.0\Samples\1033. Otherwise, go to the directory where you have Oracas installed.
    • In this directory, you will find a file called CSharpSamples.zip. Unzip this file to your preferred directory (I created a sub-directory CSharpSamples under the above directory).
    • After you unzipped the file, move to the sub-directory LinqSamples, in this sub-directory you will find another subdirectory called ExpressionTreeVisualizer. Go to this sub-directory.
    • In the ExpressionTreeVisualizer sub-directory, you will find a solution called ExpressionTreeVisualizer.sln. Open and build this solution.
    • After the build successfully completes, move to the \ExpressionTreeVisualizer\bin\Debug sub-directory. In this directory, you will find a file called ExpressionTreeVisualizer.dll. This is the actual visualizer dll used by Visual Studio.
    • Copy the ExpressionTreeVisualizer.dll to the C:\Documents and Settings\Administrator\My Documents\Visual Studio 2008\Visualizers directory (if not logged in as administrator, substitute administrator with your user name. This is the location where all Visual Studio visualizers live for your Visual Studio installation.
    • After you have completed the above steps, and have restarted Visual Studio, the following will happen when you are debugging an application with an Expression<T> instance, and you have a breakpoint on a unit of code with an Expression<T>:
      • You will see the "Looking glass" icon, indicating that a visualizer is available for the object under the cursor.
      • Click the looking glass icon.
      • The "Expression Tree Visualizer" selector will pop up, as shown below:

    LookingGlass

      • Click the pop-up, and the visualizer will show the expression tree in all of its beauty, as shown earlier.

    Creating Expression Trees

    You can create an expression tree in two different ways:

    1. You can write an Expression<T> as we did in our example in the previous section. by assigning an Expression<T> instance to a lambda expression. As we saw in the visual studio visualizer, the C# compiler automatically generated (in this case a quite elaborate) expression tree for us.
    2. You can use the Expression API in the System.Linq.Expressions namespace to manually build your own expressions. While this quite a bit more complicated and time-consuming, it does open up all kinds of possibilities, as we will see in the "Dynamic Queries" section of this post.

    We will take a closer look at each approach in the next sections.

    Creating an expression tree based upon a lambda expression

    The first approach to creating expression trees is fairly easy. You write a valid lambda expression, and supply it as the type argument to an Expression<T> instance. This is illustrated by the following code sample (this is the SimpleExample class in the SimpleExpressionTrees project of our sample code):

    1 /// <summary> 2 /// This method shows how you can create an expression, based upon 3 /// a Lambda Expression 4 /// </summary> 5 public static void CreateExpressionFromLamba() 6 { 7 // This is how you declare a lambda expression by itself 8 Func<int, int, int> addLambda = (value1, value2) => value1 + value2; 9 10 // This is how you declare an equivalent lambda expression 11 Expression<Func<int, int, int>> lambdaExpression = (value1, value2) => value1 + value2; 12 Console.WriteLine("Lambda Expression: {0}", lambdaExpression.ToString()); 13 dumpExpression(lambdaExpression); 14 15 // Compile and execute the lambda expression in the Expression<T> 16 Func<int, int, int> lambda = lambdaExpression.Compile(); 17 int v1 = 5; 18 int v2 = 10; 19 Console.WriteLine("Compiling and executing the expression"); 20 Console.WriteLine("{0} + {1} = {2}", v1, v2, lambda.Invoke(v1, v2)); 21 22 // Note how I can use statements in a lambda expression 23 Func<int, int, bool> compareLambda = 24 (val1, val2) => { if (val1 == val2) return true; else return false; }; 25 26 // The statement below will not compile, since you cannot use 27 // a lambda expressions with a statement to create an expression tree 28 //Expression<Func<int, int, bool>> compareExpression = 29 // (val1, val2) => { if (val1 == val2) return true; else return false; }; 30 31 } // method CreateExpressionFromLamba

    In line 8, we create a simply lambda expression which adds the two integers passed as arguments. In line 11, I create an expression tree, based upon an identical lambda expression. Note also, how Expression<T> has a handy ToString() override which shows the lambda expression. The output of line 12 is shown below:

    Lambda Expression: (value1, value2) => (value1 + value2)

    So, what  we get is a neat representation of the lambda expression on which the expression is based. To add some functionality to this I created a simple little dumpBLOCKED EXPRESSION function which prints out the details of an expression. The code for this method is shown below:

    1 /// <summary> 2 /// This method prints out the details of the passed-in Expression 3 /// </summary> 4 /// <typeparam name="T"></typeparam> 5 /// <param name="expression"></param> 6 private static void dumpExpression<T>(Expression<T> expression) 7 { 8 Console.WriteLine("Lambda Expression: {0}", expression.ToString()); 9 Console.WriteLine("Expression Details: "); 10 Console.WriteLine("\tExpression Body: {0}", expression.Body); 11 for (int index = 0; index < expression.Parameters.Count; index++) 12 { 13 var parameter = expression.Parameters[index]; 14 Console.WriteLine("\tParameter {0}: '{1}', Type: {2}", 15 index, parameter, parameter.Type.Name); 16 } 17 Console.WriteLine("\tNodeType: {0}", expression.NodeType); 18 }

    This code sample shows some interesting properties of the Expression<T> class:

    1. The Body property of the Expression<T> gives us the body of the lambda expression.
    2. The Parameters property returns a ReadOnlyCollection<T> where T is of type ExpressionParameter. The code simply loops over each parameter, and prints the index, name and type of each parameter. 
    3. Finally, the NodeType property provides the Node Type of the Expression. We'll have more to say about Node Types in the next section.

    When we pass our expression to this function, we get the following output, which correctly represents our expression instance.

    Lambda Expression: (value1, value2) => (value1 + value2) Expression Details: Expression Body: (value1 + value2) Parameter 0: 'value1', Type: Int32 Parameter 1: 'value2', Type: Int32 NodeType: Lambda

    When the invoke the Expression<T> Compile() method, we get our original lambda expression back, as is shown below:

    Func<int, int, int> lambda = lambdaExpression.Compile();

    Next, we can invoke the lambda  expression directly with it's Invoke() method:

    int v1 = 5; int v2 = 10; Console.WriteLine("Compiling and executing the expression"); Console.WriteLine("{0} + {1} = {2}", v1, v2, lambda.Invoke(v1, v2));

    which produces our expected output:

    Compiling and executing the expression 5 + 10 = 15

    When we go back to our first listing, we see that we can also create a lambda expression, based upon a statement, instead of a simple expression:

    1 // Note how I can use statements in a lambda expression 2 Func<int, int, bool> compareLambda = 3 (val1, val2) => { if (val1 == val2) return true; else return false; };

    However, you cannot use a lambda expression with a statement to initialize an expression. If I would attempt to compile a function with the following statement:

    // The statement below will not compile, since you cannot use // a lambda expressions with a statement to create an expression tree Expression<Func<int, int, bool>> compareExpression = (val1, val2) => { if (val1 == val2) return true; else return false; };

    The you would get the following compilation error:

    Error 1 A lambda expression with a statement body cannot be converted to an expression tree SimpleExpressionTrees

    Manually Creating an Expression Tree

    The System.Linq.Expression namespace offers a rich API, which allows you to dynamically build an expression tree of arbitrary complexity, without the limitations mentioned in the previous section. For example, the code sample below, shows how to use this API to build exactly the same expression as we did earlier in the first example of the CreateExpressionFromLamba() method:

    1 /// <summary> 2 /// In this example, we build exactly the same expression as we 3 /// did in the first example of the CreateExpressionFromLamba() 4 /// function 5 /// </summary> 6 public static void ManuallyBuildBLOCKED EXPRESSION 7 { 8 Console.WriteLine("\n\nManually Building an expression"); 9 10 // First, create the parameter expressions 11 ParameterExpression val1Expr = Expression.Parameter(typeof(int), "value1"); 12 ParameterExpression val2Expr = Expression.Parameter(typeof(int), "value2"); 13 14 // Create the "add" expression 15 BinaryExpression addExpr = BinaryExpression.Add(val1Expr, val2Expr); 16 17 // Wrap the add expression in a Lambda expression 18 var lambdaExpr = 19 Expression.Lambda<Func<int, int, int>>( 20 addExpr, new ParameterExpression[] {val1Expr, val2Expr}); 21 22 // Dump the expression 23 dumpExpression(lambdaExpr); 24 25 // Compile and execute the lambda expression in the Expression<T> 26 Func<int, int, int> lambda = lambdaExpr.Compile(); 27 int v1 = 5; 28 int v2 = 10; 29 Console.WriteLine("Compiling and executing the expression"); 30 Console.WriteLine("{0} + {1} = {2}", v1, v2, lambda.Invoke(v1, v2)); 31 32 } // method ManuallyBuildExpression

    As you can see, the code is definitely more verbose, but not necessarily complicated. First, we create two ParameterExpressions to represent the value1 and value2 parameters to the lambda expression. Next, we create an Add BinaryExpression, which adds both values together. The BinaryExpression class has 17 overloads, which allow you to create just about any binary expression you would ever need.

    Finally, we wrap our expression into a lambda expression, which is ultimately what we were planning to do from the start. Note that we need to specify the correct lambda prototype as type argument. The function arguments are the Binary Add expression, and both of our Parameter Expressions.

    To verify that we indeed created the correct expression, we passed our expression on to our trusted dumpBLOCKED EXPRESSION function. Here is the output:

    Lambda Expression: (value1, value2) => (value1 + value2) Expression Details: Expression Body: (value1 + value2) Parameter 0: 'value1', Type: Int32 Parameter 1: 'value2', Type: Int32 NodeType: Lambda

    And indeed, the output of our manually created expression tree is identical to our first expression, created directly from a lambda expression! An naturally, we can compile and invoke the expression as we did in our previous example.

    Using Expression Trees to create Dynamic  Query Expressions

    One of the interesting applications of expression trees, is the enablement of more dynamic LINQ queries. The DynamicQueryWithExpression class of the sample code illustrates this. The constructor of this class generates an integer array with 20 elements, as is shown below:

    1 public DynamicQueryWithExpressions() 2 { 3 for (int i = 0; i < 20; i++) 4 { 5 m_myInts.Add(i); 6 } 7 8 Console.WriteLine("\nDynamic Query Example"); 9 } // constructor

    The SimpleQuery() method performs a query against this list, retrieving all elements that are between 5 and 15 exclusive:

    1 /// <summary> 2 /// This method executes a simple, very straightforward query 3 /// </summary> 4 public void SimpleQuery() 5 { 6 7 var results = from i in m_myInts 8 where i > 5 && i < 15 9 orderby i 10 select i; 11 12 showResults("SimpleQuery", results); 13 14 } // method SimpleQuery

    The output from this query is shown below:

    Results from query: QueryWithDynamicParameters 7 9 11 14

    This query contains a very simple where clause that specifies our range. But what if we have a situation where we do not know at compile time what numbers we need? We might want to include some number, and at the same time, we might want to exclude some other numbers. Furthermore, the user might want to specify these numbers at runtime, through some type of user interface. In such a scenario, the above simple query construct will no longer work for us.

    Scenario's such as the one describe above are a custom fit for custom expressions. As we mentioned before, we can construct any Expresssion<T> -based expression tree we want, of arbitrarily deep complexity. In the above example, what we have a need for is a way to build AND and OR expression "chains". One we can build these expression, we can build ourselves a "power where clause" we can use for our query.

    I started writing a class to build these types of predicates, but then I came across a beautiful implementation by  Josheph Albhari, and I decided that this was so nicely done that there was no way to improve upon his code, so credit where credit is due. By the way, I really recommend Joseph Albhari's blog, he has some great C# 3.0 examples in there. The name of his class is PredicateBuilder, and the code is shown below:

    1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Linq.Expressions; 5 6 namespace SimpleExpressionTrees 7 { 8 /// <summary> 9 /// This class allows us to build AND and OR expressions 10 /// </summary> 11 public static class PredicateBuilder 12 { 13 // These expressions define a true or false expression, which are 14 // used as "anchor" expressions for build or AND or OR predicates 15 public static Expression<Func<T, bool>> True<T>() { return f => true; } 16 public static Expression<Func<T, bool>> False<T>() { return f => false; } 17 18 /// <summary> 19 /// This Extension method creates an OR Expression 20 /// </summary> 21 /// <typeparam name="T"></typeparam> 22 /// <param name="expr1"></param> 23 /// <param name="expr2"></param> 24 /// <returns></returns> 25 public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1, 26 Expression<Func<T, bool>> expr2) 27 { 28 // Invoke the second expression, passing in the parameters of the first expression 29 var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>()); 30 31 // Create the Or Expression, and wrap it in a Lamba expression 32 return Expression.Lambda<Func<T, bool>> 33 (Expression.Or(expr1.Body, invokedExpr), expr1.Parameters); 34 35 } // method Or 36 37 /// <summary> 38 /// This Extension method creates an AND expression 39 /// </summary> 40 /// <typeparam name="T"></typeparam> 41 /// <param name="expr1"></param> 42 /// <param name="expr2"></param> 43 /// <returns></returns> 44 public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1, 45 Expression<Func<T, bool>> expr2) 46 { 47 // Invoke the second expression, passing in the parameters of the first expression 48 var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>()); 49 50 // Create the And Expression, and wrap it in a Lamba expression 51 return Expression.Lambda<Func<T, bool>> 52 (Expression.And(expr1.Body, invokedExpr), expr1.Parameters); 53 54 } // method And 55 56 } // class PredicateBuilder 57 } //namespace SimpleExpressionTrees 58

    In lines 15 and 16, we have a True and a False static Expression, which can be used an "anchor points" for building an AND or and OR expression chain. The implementations of both the And and the Or methods is very elegant and straightforward. First (in lines 29 and 48), we create an InvocationExpression,  passing in the second expression and their parameters. Next, we create a BinaryExpression by performing and And or an Or  between the body of our first expression and the InvocationExpression created earlier (lines 32 and 51), and then wrap the result in a Lambda Expression. The above class can be found in the PredicateBuilder.cs class of the sample code.

    Based upon this PredicateBuilder class, I created a method in the DynamicQueryWithExpressions class that can build an OR filter chain. The code for this method is shown below:

    1 /// <summary> 2 /// This method builds up a dynamic expression with OR statements 3 /// for each number that should be included. It uses the PredicateBuilder 4 /// to build to expression 5 /// </summary> 6 /// <param name="numbersToInclude"></param> 7 /// <returns></returns> 8 private Expression<Func<int, bool>> filterByIntList(params int[] numbersToInclude) 9 { 10 // Since we are building OR statements, we start out with a FALSE expression, 11 // otherwise our OR statement would always evaluate to true.. 12 var predicate = PredicateBuilder.False <int> (); 13 14 // Loop over each number to include, and add an OR predicate 15 // to the expression 16 for (int index = 0 ; index < numbersToInclude.Length; index++) 17 { 18 int value = numbersToInclude[index]; 19 predicate = predicate.Or(i => i == value); 20 } 21 return predicate; 22 23 } // method filterByIntList

    In line 12, we set our "anchor expression", which should be:

    • False if we are building an OR filter chain (otherwise our result would always be true).
    • True is we are building an AND filter chain (otherwise our result would always be false)

    We get the arguments to include in the numbersToInclude params array, so we simply need to loop over each element of the array, and invoke the predicate.Or() method with the lambda expression:

    i => i == value

    as argument. This lamda expression will guarantee that our value is included in the results if it is present in the source array. So, in effect what we are doing during this loop is building and expression which gets more and more complex, and finally includes all values that should be used in the Where clause of our query.

    Below is then finally the query which uses this expression:

    1 /// <summary> 2 /// This method extends our query with dynamic and and or elements 3 /// </summary> 4 /// <param name="numbersToFind"></param> 5 public void QueryWithDynamicParameters(params int[] numbersToInclude) 6 { 7 Expression<Func<int, bool>> predicate = filterByIntList(numbersToInclude); 8 Func<int, bool> isInArray = predicate.Compile(); 9 10 var results = from value in m_myInts.Where(isInArray) 11 where value > 5 && value < 15 12 orderby value 13 select value; 14 15 showResults("QueryWithDynamicParameters", results); 16 17 } // method QueryWithDynamicParameters

    in line 7 be invoke our method to create our expression,  and in line 8, we compile the expression, which gives us back a lambda expression. Note that we selected to actually apply the lambda expression directly on the m_myInts array, so we can use the power of a "standard, static" where clause together with the power of a dynamically created expression.  The application of the Where condition on the array effectively invokes the following extension method of IEnumerable<T>:

    public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate);

    The invocation of this method and the results are shown below:

    1 // These examples show how to create a dynamic 2 // query with an Expression 3 DynamicQueryWithExpressions dynQuery = new DynamicQueryWithExpressions(); 4 .... 5 dynQuery.QueryWithDynamicParameters(new int[] { 2, 7, 9, 11, 14, 17 }); 6 7 Results from query: QueryWithDynamicParameters 8 7 9 9 10 11 11 14

    As you see, all supplied values are included except for 2 and 17, because they do not satisfy the "static" where clause.

    The above example is very simple, but you can see how you could easily build powerful expression generators with classes like the PredicateBuilder.

    Expression Trees and LINQ Query Providers

    Besides enabling you to create dynamic queries, expression trees are also used in a "deferred execution" mode in LINQ. For example, in LINQ to SQL, here is the sequence of events:

    1. The user writes a method which contains a LINQ-to-SQL query.
    2. The compiler compiles the SQL-like query into a sequence of method calls.
    3. The compiler then compiles the series of method calls into an expression tree.
    4. The expression trees is used by the LINQ-to-SQL infrastructure to create an optimized T-SQL statement. So, in this case, the expression tree is NEVER directly executed, it is simply used as a rich data structure, from which we can create a Transact-SQL query.
    5. The first time the results of the query are actually accessed, the SQL Statement is sent to the designated SQL server and executed, and the results are returned to the client.

    Note that the above description is greatly simplified. The next (and final) installment of this series will dive deep into the bowels of the interfaces and classes that enable all of this to happen. Also, note that this model is not necessarily limited to LINQ-to-SQL. Most (if not all) LINQ providers use an identical model where some type of query is created from the expression tree, and executed when the results of the query are first accessed.

    Posted Aug 18 2007, 05:33 PM by bennie with 4 comment(s)
    Filed under: , ,
  • New Features in C# 3.0, Part 5: Lambda Expressions Source Code is Now Available

    Hello, I (finally) got around to uploading the code for part 5 of my C# 3.0 article series. I also finalized the text of the post, adding a section on extension methods and lambda functions at the end of the article.

    If you read the article, you will notice my excitement around lambda expression, I think they really move C# ahead with leaps and bounds, and open up the possibilities of endless language extensions, especially combined with expression trees, which is curiously enough the topic of of my next post!

    Stay  tuned!

  • New Features in C# 3.0, Part 5: Lambda Expressions

    Definition

    A Lambda Expression is basically a logic evolution of the concept of anonymous functions, which was introduced with C# 2.0. Anonymous functions basically allow the body of a function to be written "in-line", where we would normally expect a delegate to be invoked.

    Lambda expressions provide a much more concise, functional and targeted syntax for writing anonymous methods. In LINQ they are used all the time. A LINQ query is basically a tree of Lambda expressions. We will look at expressions trees in detail in the next post in this series.

    Lambda expressions provide a very compact and type-safe way to write functions that can be passed as function arguments to another function for subsequent evaluation.

    A Bit of history

    In this section, we will look at the evolution in C# from delegates, to anonymous methods and finally to Lambda expressions. The code for this section can be found in the "SimpleExamples" project of the download code for this article.

    In this "history" section, we will take a simple problem, which in this case is the indirect execution of a block  of code, and solve it using different methods:

    • Delegates
    • Anonymous Methods
    • Lambda Expressions

    Delegates

    Since it inception C# and .NET 1.0 have supported the concept of a delegate. A delegate is basically a type-safe function pointer. Delegates specify a method to call and optionally an object to call the method on. Typically, delegate are used to implement callbacks and event listeners.

    A simple example of a class that uses a delegate is shown below (this class is part of the code project mentioned earlier):

    1 /// <summary> 2 /// This class invokes a method through a delegate 3 /// </summary> 4 public class ClassWithDelegate 5 { 6 // This is our delegate declaration 7 private delegate void MyDelegate(int myInt, string myString); 8 9 // This is the method which will invoke "Bar" through a delegate 10 public void InvokeMethodThroughDelegate() 11 { 12 MyDelegate myDelegate = new MyDelegate(Bar); 13 myDelegate(10, "test"); 14 } 15 16 private void Bar(int anInt, string aString) 17 { 18 Console.WriteLine("\tThis is a method invoked through a delegate, params: {0} and {1}", 19 anInt, aString); 20 } 21 22 } // class ClassWithDelegate

    First, on line 7 we have our delegate declaration, which basically specifies the name of our delegate and the signature of the to-be invoked method. The method we want to invoke is Bar, the body of which is specified from line 16 through line 20 in the code.

    In line 12, notice how we have to "new up" a new instance of our delegate, specifying the name of the method (Bar) as an argument. In the next line, we can then call the method through the delegate, passing in the function arguments.

    Note that delegates are type safe, so if at line 12, I specified a method (say Foo) as the new argument, with a signature that did not match the signature specified by the  MyDelegate specification, I would have received a compiler error:

    Error 1 No overload for 'Foo' matches delegate SimpleExamples

    While delegates definitely have their use, and will continue to serve us well in the future, in the above example the code is pretty verbose. Basically, all we want to do is execute a block of code, but I need my delegate declaration, my Bar method, I need to new up a Delegate instance before I finally can invoked the code through the delegate. Isn't there a better way? Yes, there is.. enter: "Anonymous Methods"!

    Anonymous Methods

    An anonymous method is a new feature in C# 2.0 that lets you define an anonymous (that is, nameless) method that can be called by a delegate. Just like a regular method, a anonymous method can take any number of parameters. An anonymous method is defined inline, and not as a member of any class.

    Anonymous methods can be used anywhere that a delegate is expected.  You can pass an anonymous method into any method that accepts the appropriate delegate type as a parameter.

    Going back to our example, here is the code for the "ClassWithAnonMethod" class with our sample project:

    1 public class ClassWithAnonMethod 2 { 3 // This is the delegate declaration 4 private delegate void MyDelegate(int myInt, string myString); 5 6 // This is the method which will calls an anonymous method 7 // through a delegate 8 public void InvokeMethodThroughAnonMethod() 9 { 10 MyDelegate myDelegate = delegate(int anInt, string aString) 11 { 12 Console.WriteLine("\tThis is the anonymous method, params: {0} and {1}", 13 anInt, aString); 14 }; 15 16 myDelegate(10, "test"); 17 } 18 19 } // class ClassWithAnonMethod 20

    As you can see, our delegate declaration is still there, but our "Bar" method has now been replaced with an anonymous method, defined in lines 12 and 13. The anonymous method itself is still invoked through the delegate in the same way at line 16. This code is a lot more compact and easier to read in some situations (as long as the code in the anonymous method is limited to a couple of lines of code).

    A Zen moment...

    My last comment (about anonymous functions) again makes me think that it would be a good idea to write a closure post at the end of this series, where we do kind of a "reset", and look at where it would be appropriate to use each feature mentioned in this series. In the programming world, you basically have two types of people (I am over-simplifying here, I know):

    1. The first type are the folks who love all of this "new stuff", and would go out of their way to use every feature possible.
    2. The second group of folks just wants to get  the job done. From these folks you often hear comments like: 'this is very cool stuff, but it just need to get this project done, and this stuff is not going to help me get there any faster!"

    I think both groups of people have a point, and the "sweet spot" is probably somewhere in between both opinions. I don't see myself driving to work every day, thinking: "Today I am going to write a killer lamba expression tree, and create a cool new query syntax" ;-), but I can see a use for each of the features we talk about so far, as long as it is applied in the right context. And of course, when it comes to LINQ, DLINQ and XLINQ itself, I think those feature will indeed change the way we work, and they will be incredible time savers indeed!

    Ok, that was my short "Zen moment", sorry for the interruption, back to Lambda expressions" now!

    Lambda Expressions

    Lambda expression provide a more concise, functional syntax for writing an anonymous method. Compared to anonymous methods they provide a very compact and more type-safe way to write small functions that can be passed as arguments for subsequent evaluation. The Select, Where, Sort etc. clauses in LINQ are basically all written as Lambda expressions.

    Below is a small code sample. This is the "ClassWithLambda" class from out sample project:

    1 public class ClassWithLambda 2 { 3 // This is the delegate declaration 4 private delegate void MyDelegate(int myInt, string myString); 5 6 public void InvokeMethodWithLambdaBLOCKED EXPRESSION 7 { 8 // Now our delegate uses a Lambda expression 9 MyDelegate myDelegate = 10 (value1, value2) => Console.WriteLine( 11 "\tThis is lambda expression, params: {0} and {1}", value1, value2); 12 13 myDelegate(10, "test"); 14 }

    Note that we still have our Delegate declaration at line 4. The Lambda expression itself is on lines 10 and 11.

    In C# 3.0 a lambda expression is syntactically written as a parameter list, followed by a =>token, and then followed by the expression or statement block to execute when the expression is invoked. In it simplest form, a lambda expression can look like this:

    params => expression

    You can omit the parenthesis around the parameters when you only have one parameter.

    In our case, our lambda expression looks like this:

    (value1, value2) => Console.WriteLine(....)

    Note that I did not bother to specify the types of both value1 and value2. Now, there is nothing that prohibits me from doing so, so I could have written:

    (int value1, string value2) => Console.WriteLine(....)

    In the first example, the compiler will use type inference to  find out what the types of passed-in parameters are, so the run-time overhead for both types will be exactly the same.

    The expression you write at the right side of the => token can be any expression or statement block, and it can consume the passed-in parameters.

    Now, you might look at this and say "big deal", now what does  this offer me that I cannot do with anonymous method? Well, let's take a look at that in the next section!

    Using Lambda Expressions as Parameters to Functions

    This this section, we will look at one of the most powerful features of lambda expressions, which is its ability to be passed as parameters to functions in a type-safe way with automatic type inference. During this section, we are assuming that we are creating a Math Library, and we are going to pass in a function that performs the actual math operation as a lambda expression. We will start out simple, and add more powerful features as we go along.

    Using hard-coded argument types

    Below is our first example:

    1 // This function takes a lambda as parameter with hard-coded 2 // types for the parameters (in this case all integers) 3 public int PerformMathFunction(Func<int, int, int> lambdaExpression, int val1, int val2) 4 { 5 int result = lambdaExpression(val1, val2); 6 Console.WriteLine("\tPerformMathFunction, val1: {0}, val2: {1}, result: {2}", 7 val1, val2, result); 8 9 return result; 10 }

    the parameter:

    Func<int, int, int> lambdaExpression

    specifies that we are passing in a lambda expression, which takes two integers (the first two parameters are integers), and returns an integer. In a Func specification like this, the last type is always the return type. So far example an expression like this:

    Func<int, double> lambdaExpression

    specifies that we are passing in a lambda expression that takes one parameter that is an integer, and returns a double, or even simpler:

    Func<decimal> lambdaExpression

    specifies that we are passing in a lambda expression that returns a double.

    We are invoking the passed-in lambda expression as follows:

    int result = lambdaExpression(val1, val2);

    In this case we know that our lambda expression is returning an integer, so we can assign the result of our expression to an integer. The rest of the above method simply prints our the passed-in values and the result, and returns the result.

    Below is an example of how you invoke the PerformMathFunction() method:

    1 // In the remainder of this method, we show how you can pass lamda 2 // expressions as arguments to a method 3 ClassWithLambdaExpressionAsParam paramClass = 4 new ClassWithLambdaExpressionAsParam(); 5 6 // Simple examples without type inference 7 paramClass.PerformMathFunction((int val1, int val2) => val1 + val2, 10, 20); 8 paramClass.PerformMathFunction((int val1, int val2) => val1 * val2, 10, 20);

    The lambda expressions that we pass in are:

    (int val1, int val2) => val1 + val2    -and-

    (int val1, int val2) => val1 * val2   

    The above example produces the following output:

    PerformMathFunction, val1: 10, val2: 20, result: 30 PerformMathFunction, val1: 10, val2: 20, result: 200

    While the above example nicely illustrates how we can pass in a lambda expressions into a method, it has one main drawback: It only works with arguments of type Integer. In the next example, we will see how we can get around this.

    Using Generic arguments Types

    Below is a new version of our method:

    1 // This function uses Type Inference ("T"), but forces all parameters to be of the 2 // same type, so both math parameters and the return type are of the same Type T 3 public T PerformMathFunctionWithTypeInference<T>(Func<T, T, T> lambdaExpression, T val1, T val2) 4 { 5 T result = lambdaExpression(val1, val2); 6 Console.WriteLine("\tPerformMathFunctionWithTypeInference, val1: {0}, val2: {1}, result: {2}", 7 val1, val2, result); 8 9 Console.WriteLine("\t\tType of T: {0}", typeof(T).Name); 10 11 return result; 12 }

    Now, our passed-in lambda expression has changed to:

    Func<T, T, T> lambdaExpression

    Now, we are using a generically typed parameter, and the compiler will use type interference to determine what the type of T is. Note that we used the same type "T" everywhere, so we expect both input arguments and the return type to be of the same type. Compared to our previous example, our method has become a lot more flexible though, since we now can pass in an argument of any type, and the compiler will do the work of figuring out what the type is.

    Note also that since our Method PerformMathFunctionWithTypeInference() now basically is a generic method, we need to specify the generic parameter <T> as part of its name:

    public T PerformMathFunctionWithTypeInference<T>(...)

    Note that our method also prints out the name of the type "T", so in our output, we will be able to verify that the compiler indeed inferred the correct type.

    So, if we call this method as follows:

    1 // In the remainder of this method, we show how you can pass lamda 2 // expressions as arguments to a method 3 ClassWithLambdaExpressionAsParam paramClass = 4 new ClassWithLambdaExpressionAsParam(); 5 6 // Advanced examples with type inference 7 paramClass.PerformMathFunctionWithTypeInference((val1, val2) => val1 / val2, 200.0, 5.0);

    Our output will look as follows:

    PerformMathFunctionWithTypeInference, val1: 200, val2: 5, result: 40 Type of T: Double

    Because we passed in variables 200.0 and 5.0, the compiler correctly inferred that the type of T is indeed Double.

    In our next example, we will take this example one step further, and vary the output type of the result.

    Using different Generic types for the Arguments

    As a next step, we will extend our example once more, and allow the return type of our lambda function to be different then the type of the passed-in parameters.  The code for the example is shown below:

    1 // This function also takes a lambda parameters, but it allows the caller to specify a 2 // different type for the return type of the lambda (type "R"). Both parameters are expected 3 // to be of the same type "T" 4 public R PerformMathFunctionGenericFlexReturnType<R, T>(Func<T, T, R> lambdaExpression, T val1, T val2) 5 { 6 R result = lambdaExpression(val1, val2); 7 Console.WriteLine("\tPerformMathFunctionGenericFlexReturnType, val1: {0}, val2: {1}, result: {2}", 8 val1, val2, result); 9 10 Console.WriteLine("\t\tType of T: {0}, Type of R: {1}", typeof(T).Name, typeof(R).Name); 11 12 return result; 13 }

    Notice the signature of our lambda expression:

    Func<T, T, R> lambdaExpression

    Indicating that the return type of our lambda expression is now the generic type "R", while the input parameters have the generic type "T". Notice also how we had to add the additional generic type parameter to our function signature:

    public R PerformMathFunctionGenericFlexReturnType<R, T>(....)

    In our function, we can now  use the return type "R" as the return type of the lambda expression. In this case, we also selected to print out both the name of the types of "T" and "R". An example invocation method is shown below:

    1 // In the remainder of this method, we show how you can pass lamda 2 // expressions as arguments to a method 3 ClassWithLambdaExpressionAsParam paramClass = 4 new ClassWithLambdaExpressionAsParam(); 5 6 paramClass.PerformMathFunctionGenericFlexReturnType((val1, val2) => (int)(val1 / val2), 5.0, 2.0);

    So, our lambda expression is in this case:

    (val1, val2) => (int)(val1 / val2)

    When we run this sample, we get the following output:

    PerformMathFunctionGenericFlexReturnType, val1: 5, val2: 2, result: 2 Type of T: Double, Type of R: Int32

    Because our passed-in lambda expression did a cast of the result to integer, the compiler correctly inferred that the type of "R" is indeed System.Int32.

    Lambda Expressions and Extension Methods

    Introduction

    We talked about extension methods in part 4 of this series. Extension methods can basically be defined for any type, and long as the type itself is not static. We you combine Lambda expressions with extension methods, you get a very powerful brew. It is fact this combination that is at the very core of the query syntax of LINQ.

    Microsoft has create a large number of extension methods for the IEnumberable<T> type. IEnumerable<T> is a logical choice since this interface is supported by most generics collections in C#. All of these extensions are defined  in the namespace System.Linq, in the static class Enumerable:

    using System; using System.Collections; using System.Collections.Generic; using System.Runtime.CompilerServices; namespace System.Linq { // Summary: // Provides a set of static (Shared in Visual Basic) methods for querying objects // that implement System.Collections.Generic.IEnumerable<T>. public static class Enumerable { // Summary: // Applies an accumulator function over a sequence. // // Parameters: // source: // An System.Collections.Generic.IEnumerable<T> to aggregate over. // // Parameters: // // func: // An accumulator function to be invoked on each element. // // Type parameters: // TSource: // The type of the elements of source. // // Returns: // The final accumulator value. // // Exceptions: // System.ArgumentNullException: // source or func is null. // // System.InvalidOperationException: // source contains no elements. public static TSource Aggregate<TSource>(this IEnumerable<TSource> source, Func<TSource, TSource, TSource> func); ...... } }

    Now, I wanted to find out how many extensions methods there were exactly, and give the reader some idea of how many different overloads there were for every method, but instead of doing this manual, I decided to write a little LINQ query (you know I had to  ;-)!. This is the code:

    1 public static void DetermineNumberOfExtensionMethodsForIEnumerable() 2 { 3 // Write the total number of methods 4 Console.WriteLine( 5 "Total number of methods in System.Linq.Enumerable: {0}", 6 typeof(System.Linq.Enumerable).GetMethods().Length); 7 8 // This query gets the name and number of overloaded methods 9 var overloads = 10 from method in typeof(System.Linq.Enumerable).GetMethods() 11 where method.IsStatic == true 12 group method by method.Name into m 13 orderby m.Key 14 select new 15 { 16 MethodName = m.Key, 17 OverloadCount = m.Count() 18 }; 19 20 Console.WriteLine(Environment.NewLine); 21 22 // Write out the overloads 23 foreach (var overload in overloads) 24 { 25 Console.WriteLine( 26 string.Format("Method: '{0}', # of overloads: {1}", 27 overload.MethodName, overload.OverloadCount)); 28 } 29 30 } // method DetermineNumberOfExtensionMethodsForIEnumerable 31

    I will no go over the detailed syntax here, since we have not talked about expression trees yet, but basically first this method uses good old reflection to get the total number of methods, and next, its uses a very simply LINQ query to group the methods in System.Linq.Enumerable by method name, and selects the results in an anonymous type which contains two properties:

    1. The method name
    2. The number of overloads

    It uses a simple group by and order by to group and sort the results. Look like good old fashioned SQL doesn't it?

    Here are the result of the above method:

    Total number of methods in System.Linq.Enumerable: 178 Method: 'Aggregate', # of overloads: 3 Method: 'All', # of overloads: 1 Method: 'Any', # of overloads: 2 Method: 'AsEnumerable', # of overloads: 1 Method: 'Average', # of overloads: 20 Method: 'Cast', # of overloads: 1 Method: 'Concat', # of overloads: 1 Method: 'Contains', # of overloads: 2 Method: 'Count', # of overloads: 2 Method: 'DefaultIfEmpty', # of overloads: 2 Method: 'Distinct', # of overloads: 2 Method: 'ElementAt', # of overloads: 1 Method: 'ElementAtOrDefault', # of overloads: 1 Method: 'Empty', # of overloads: 1 Method: 'Except', # of overloads: 2 Method: 'First', # of overloads: 2 Method: 'FirstOrDefault', # of overloads: 2 Method: 'GroupBy', # of overloads: 8 Method: 'GroupJoin', # of overloads: 2 Method: 'Intersect', # of overloads: 2 Method: 'Join', # of overloads: 2 Method: 'Last', # of overloads: 2 Method: 'LastOrDefault', # of overloads: 2 Method: 'LongCount', # of overloads: 2 Method: 'Max', # of overloads: 22 Method: 'Min', # of overloads: 22 Method: 'OfType', # of overloads: 1 Method: 'OrderBy', # of overloads: 2 Method: 'OrderByDescending', # of overloads: 2 Method: 'Range', # of overloads: 1 Method: 'Repeat', # of overloads: 1 Method: 'Reverse', # of overloads: 1 Method: 'Select', # of overloads: 2 Method: 'SelectMany', # of overloads: 4 Method: 'SequenceEqual', # of overloads: 2 Method: 'Single', # of overloads: 2 Method: 'SingleOrDefault', # of overloads: 2 Method: 'Skip', # of overloads: 1 Method: 'SkipWhile', # of overloads: 2 Method: 'Sum', # of overloads: 20 Method: 'Take', # of overloads: 1 Method: 'TakeWhile', # of overloads: 2 Method: 'ThenBy', # of overloads: 2 Method: 'ThenByDescending', # of overloads: 2 Method: 'ToArray', # of overloads: 1 Method: 'ToDictionary', # of overloads: 4 Method: 'ToList', # of overloads: 1 Method: 'ToLookup', # of overloads: 4 Method: 'Union', # of overloads: 2 Method: 'Where', # of overloads: 2

    When you study this list carefully, you recognize a large number of SQL constructs, such as Union, Where, Join, Intersect, OrderBy etc..

    Manually Invoking Extension Methods with Lambda Expressions

    Using Type Inference

    In the previous example, we jumped ahead a bit, directly to "pure" LINQ query syntax. Sorry about that, I just wanted to make sure that you guys stayed awake reading this article;-) In this section, we will take the LINQ query from the previous section, and play the role of compiler by manually writing the statement that the compiler generates for us when executing the query. Note that this will be an "unofficial" translation. The "real" translation is done with expression trees, which we will take a look at in our next post.

    Let's summarize first what we need to do:

    1. We need to get an array of all the methods in System.Linq.Enumerable.
    2. Next, we filter this list by only including the static methods
    3. Then, we order this group by Method Name
    4. Next, we need to group the result of step 2 by Method Name
    5. Finally, we loop over each tuple in the group, and print out the method name, and the count of methods, which is basically the number of overloads for the method.

    Ok, that does not look difficult at all, so let's get to work. Below is the code for the first version of this implementation:

    1 public static void ExampleUsingTypeInference() 2 { 3 Console.WriteLine("\nNo query, strongly typed variables" + Environment.NewLine); 4 5 // First, get all methods in the class 6 var methods = typeof(System.Linq.Enumerable).GetMethods(); 7 Console.WriteLine( 8 "Total number of methods in System.Linq.Enumerable: {0}", 9 methods.Length); 10 11 // Now, get the static methods 12 var staticMethods = 13 methods.Where(m => m.IsStatic == true); 14 15 // Now, order by name 16 var orderedStaticMethods = 17 staticMethods.OrderBy(m => m.Name); 18 19 // Next, group by name 20 var methodGroups = orderedStaticMethods.GroupBy(m => m.Name); 21 22 // Iterate over each group, print out the key (which is the Method Name, and the count of 23 // methods in the Group 24 foreach (var methodGroup in methodGroups) 25 { 26 Console.WriteLine( 27 string.Format("Method: '{0}', # of overloads: {1}", 28 methodGroup.Key, methodGroup.Count())); 29 } 30 } // method ExampleUsingTypeInference

    The first important fact that you probably notice is my heavy use of type inference. I use implicitly typed local variables pretty much all over the place, because at this point, I was not interested in the detailed data types returned by each of the extension methods. That's something we worry about in the next section..

    In line 6, we get the type of System.Linq.Enumerable, and use GetMethods() to get all of the methods of the type. This returns me an array of MethodInfo's, but I don't really worry about that, so I use a var for the result. It is important to know though that whatever the type is of methods, it will support the IEnumerable<T> interface (this interface is supported by pretty much all array and generic collection types in .NET).

    Next, we use the Where extension method of IENumerable<T> to filter out just the static methods in lines 12 and 13.  The lambda expression that we pass in is:

     m => m.IsStatic == true

    When the compiler looks at this lambda expression, it will use type inference to infer the following:

    • Since GetMethods() returned an array of MethodInfo's, m must be of type MethodInfo.
    • The expression body of our lambda expression returns a boolean, since we have a boolean expression

    Again, we don't care about the return type of this method, so we use the implicitly typed local variable staticMethods to store the result.

    Next, we need to order by name, another IEnumerable<T> extension method OrderBy can do this for us. The lambda expression we pass in in lines 16 and 17  specifies the Name of the method, so we  are indeed sorting by method name.

    In line 20 we use the GroupBy IEnumerable<T> extension method to sort the methods by name. Again, we assign this to a var (methodGroups). In a group, the identifier of the group can be accessed by the Key property (which is our case is the method name, because we grouped by method name). We can also apply aggregate functions to a group, in our case we use the Count() method in line 28 to get the count of the methods (i.e. "overloads") in each group.

    When you run this code, you will get exactly the same result as the result you got with the LINQ query, which proves that our analysis process was correct. This also shows us that nothing "magical" is going on. The only real processing here was the invocation of IEnumerable<T> extension methods with very simple lambda expressions.

    Using Explicit Types

    Just to show how type inference makes our lives easy, I have taken the above example, but this time, I have used the "real" types returned from the extension methods, instead of relying on type inference. Below is the code:

    1 public static void ExampleUsingStrongTyping() 2 { 3 Console.WriteLine("\nNo query, strongly typed variables" + Environment.NewLine); 4 5 // First, get all methods in the class 6 System.Reflection.MethodInfo[] methods = typeof(System.Linq.Enumerable).GetMethods(); 7 Console.WriteLine( 8 "Total number of methods in System.Linq.Enumerable: {0}", 9 methods.Length); 10 11 // Now, get the static methods 12 IEnumerable<System.Reflection.MethodInfo> staticMethods = 13 methods.Where(m => m.IsStatic == true); 14 15 // Now, order by name 16 IOrderedEnumerable<System.Reflection.MethodInfo> orderedStaticMethods = 17 staticMethods.OrderBy(m => m.Name); 18 19 // Next, group by name 20 IEnumerable<IGrouping<string, System.Reflection.MethodInfo>> methodGroups = 21 orderedStaticMethods.GroupBy(m => m.Name); 22 23 // Iterate over each group, print out the key (which is the Method Name, and the count of 24 // methods in the Group 25 foreach (IGrouping<string, System.Reflection.MethodInfo> methodGroup in methodGroups) 26 { 27 Console.WriteLine( 28 string.Format("Method: '{0}', # of overloads: {1}", 29 methodGroup.Key, methodGroup.Count())); 30 } 31 } // method ExampleUsingStrongTyping

    As you can see, no more var's in the above code. Although the code is a bit more complex, the types used make sense, and are really nothing new. The only interface that is really new to us is the IGrouping interface, which represents a query grouping:

    1 namespace System.Linq 2 { 3 // Summary: 4 // Represents a collection of objects that have a common key. 5 // 6 // Type parameters: 7 // TKey: 8 // The type of the key of the System.Linq.IGrouping<TKey,TElement>. 9 // 10 // Type parameters: 11 // 12 // TElement: 13 // The type of the values in the System.Linq.IGrouping<TKey,TElement>. 14 public interface IGrouping<TKey, TElement> : IEnumerable<TElement>, IEnumerable 15 { 16 // Summary: 17 // Gets the key of the System.Linq.IGrouping<TKey,TElement>. 18 // 19 // Returns: 20 // The key of the System.Linq.IGrouping<TKey,TElement>. 21 TKey Key { get; } 22 } 23 }

    From the above interface definition, you notice the read-only Key attribute, which represents the identifier of the grouping. Also, a number of overloads in IEnumerable<T> take IGrouping arguments, and allow you to apply aggregate functions to then, such as Count(), Sum(), Avg() etc.. which comes in very handy in a number of common queries.

    Passing Lambda Expressions to Custom Extension Methods

    When you write your own extension methods, your methods can also take lambda expressions to enhance the flexibility of the method. Below is a very simple System.String extension method:

    1 public static string ManipulateCharacterWithinString( 2 this String str, Func<char, string> manipulateFunc, char ch) 3 { 4 string subStr = manipulateFunc(ch); 5 return str.Replace(ch.ToString(), subStr); 6 7 } // method DuplicateCharacterWithString 8

     This extension method is very simple.It takes a lambda expression called manipulateFunc, which can translate and character into a string. The extension method will then perform a replace in the source string from the original character to the string created by the Lambda expression.

    Below is an example of some invocations of this extension method:

    1 Console.WriteLine("\nString extension method taking a lambda expression"); 2 string str = "test"; 3 string newStr = 4 str.ManipulateCharacterWithinString( 5 (charToManipulate) => charToManipulate.ToString() + 6 charToManipulate.ToString(), 7 'e'); 8 Console.WriteLine("Old string: {0}, new String: {1}", str, newStr); 9 10 string otherNewString = 11 str.ManipulateCharacterWithinString( 12 (charToManipulate) => charToManipulate.ToString() + "#", 'e'); 13 Console.WriteLine("Old string: {0}, new String: {1}", str, otherNewString); 14

    The first lambda expression basically duplicates the passed-in character, while the second lambda expression extends the character with the "#" character.

    The above sample will produce the following output:

    String extension method taking a lambda expression Old string: test, new String: teest Old string: test, new String: te#st

    and, as you can see the correct substitutions were performed.

    Wrap Up

    Sorry about the length of this post. We had a lot to cover here:

    • First, we compared a lambda expression to classic delegates and anonymous functions
    • Next, we looked at how you can pass lambda expressions as function arguments, with or without type inference.
    • Finally, we looked at the powerful combination of extension methods and lambda expression, and we saw how this forms the cornerstone of the LINQ query sub-system.

    In the next section, we take a look at expression trees, which is the mechanism that allows us to create a custom language syntax, such as the LINQ query syntax.

    I encourage you to download the corresponding sample code, and as always, feedback is very much appreciated.

  • New Features in C# 3.0. Part 4 : Extension Methods

    Definition

    An extension method is a method that you can use to extend the functionality of an existing type. This type can be an custom class that you have created, a standard BCL class such as System.String, or any interface, such as IEnumerable. Once you have created an extension method for the type, you can use the extension method as if it was a standard method of that type. From a client programmer's point of view, the extension method and the standard method of the type are indistinguishable.

    Note: the code for this article can be downloaded here. The download contains a Orcas Beta 2 Solution. Each section in this post will name the appropriate project within the solution that applies to the section.

    Steps to Create an Extension Method

    If you want to extend an existing type with an extension method, follow these steps:

    1. Define a public static class.
    2. Define a public static method in this above class. The first method of this class should be the data type for which you want to define the extension method.
    3. Use the this keyword as the name of the first argument of the above method. The this keyword denotes the method as an extension method.

    Examples

    Example 1: User-Created class

    Say you have written and deployed the following class:

    1 public class MyMathClass 2 { 3 public double Add(double var1, double var2) 4 { 5 return var1 + var2; 6 } 7 8 public double Subtract(double var1, double var2) 9 { 10 return var1 - var2; 11 } 12 } // class MyMathClass

    After the class has been successfully used in production, your customer asks you the add a Multiply method to your class. Since you do not want to re-deploy your entire application, you decide to write an extension method for the class, and deploy it in it's own assembly. Below is the code for the extension method:

    1 /// <summary> 2 /// This is my Math Extensions class 3 /// </summary> 4 public static class MyMathExtensions 5 { 6 // The first argument of a class extension should always be named "this", and 7 // should have the Type of the Type you want to extend (in this class MyMathClass) 8 public static double Multiply(this MyMathClass math, double var1, double var2) 9 { 10 return var1 * var2; 11 12 } // method Multiply 13 14 } // class MyMathExtensions 15

    As you can see, this method adheres to the rules defined for an extension method:

    • It is defined in a public, static class.
    • It is a static method
    • It's first argument is named this, and is of type MyMathClass, which is the type that we want to extend.

    Below is a code sample that uses both the standard methods and the extension method, as you can see, the invocation method is the same for all 3 methods:

    1 class Program 2 { 3 static void Main(string[] args) 4 { 5 // The first example method uses the methods in the MyMath class 6 MyMathClass math = new MyMathClass(); 7 Console.WriteLine("5 + 10 = {0}", math.Add(5.0, 10.0)); 8 Console.WriteLine("10 - 2 = {0}", math.Subtract(10.0, 2.0)); 9 10 // This line used the "Multiply" extension method 11 Console.WriteLine("3 * 8 = {0}", math.Multiply(3, 8)); 12 13 } // method Main 14 } // class Program

    The output is shown below:

    5 + 10 = 15 10 - 2 = 8 3 * 8 = 24

    You can find the code for this example in the UserDefinedClass project of the download solution.

    Example 2: Extending a BCL class

    In this example, we will take the System.Collections.ArrayList class, and extend it in two ways:

    • With the current API, a client can only insert a single value with the Insert method. We want to create an extension method which will overload the built-in Insert method to allow for the insertion of multiple values.
    • To view our results, we will also add a Print extension method to provide a clean printout of the values in our ArrayList instance.
    Overloading the Insert method

    The standard prototype of the insert method for the ArrayList class looks as follows:

    void ArrayList,Insert(int index, object value);

    so, we can insert a single value, but we have no ability to add a whole list of values, which might be desirable (you have the AddRange method, but that only allows for the addition of values at the end of  the ArrayList). Our extension method looks as follows:

    1 // This class contains our Array List Extensions 2 public static class ArrayListExtensions 3 { 4 /// <summary> 5 /// This is our extension method for the Array class 6 /// </summary> 7 /// <param name="array"></param> 8 /// <param name="startIndex"></param> 9 /// <param name="values"></param> 10 public static void Insert(this ArrayList array, int startIndex, params object[] values) 11 { 12 // First, check the start index 13 if (startIndex > array.Count) 14 { 15 return; 16 } 17 18 // Add the values 19 foreach (object obj in values) 20 { 21 array.Insert(startIndex++, obj); 22 } 23 } // method Insert 24 ... 25 }// class ArrayListExtensions

    So, this method uses the params keyword to allows for an arbitrary list of values to be inserted. The method verifies the validity of the startIndex, and then inserts each of the values, adjusting the startIndex after each insert.

    The important fact to take away from this example is that you can use extension methods to overload existing methods of a type.

    The Print extension method is shown below:

    1 // This class contains our Array List Extensions 2 public static class ArrayListExtensions 3 { 4 .... 5 /// <summary> 6 /// This extension method prints out the content of the Array 7 /// </summary> 8 /// <param name="array"></param> 9 public static void Print(this ArrayList array) 10 { 11 Console.WriteLine("Array Contents"); 12 for (int i = 0; i < array.Count; i++) 13 { 14 Console.WriteLine("\tIndex: {0}\tValue: {1}", i, arrayIdea); 15 } 16 } // method Print 17 18 }// class ArrayListExtensions 19

    A usage code sample is shown below (all of these examples are contained in the ExtendBCL project of the download code):

    1 static void Main(string[] args) 2 { 3 // Create the array list, and use the "standard" 4 // method to insert a single element 5 ArrayList list = new ArrayList(); 6 list.Insert(0, 101); 7 8 // Now, use the extension method to insert a whole range 9 // of values 10 list.Insert(1, 10, 20, 30, 40, 50); 11 12 13 // Finally, use the Print extension method to 14 // print the content of the Array 15 list.Print(); 16 17 } // method Main

    The above code invokes both the overloaded Insert method and the Print Extension method.

    The output of this method is shown below:

    Array Contents Index: 0 Value: 101 Index: 1 Value: 10 Index: 2 Value: 20 Index: 3 Value: 30 Index: 4 Value: 40 Index: 5 Value: 50

    Note that our above example covered a non-generic collection type, but of course extension method can be applied to any type, including collection classes from the System.Collections.Generics namespace.

    Example 3: Extending and Interface

    You can also create extension methods for interface, be it your own interfaces, our BCL interface. For  example, below is a very simple extension method for IEnumerable<T>. The method returns the actual value from MoveNext() and is called MoveToNextElement():

    1 /// <summary> 2 /// This class provides a simple extension method for "IEnumerator<T>" 3 /// </summary> 4 public static class IEnumeratorExtension 5 { 6 /// <summary> 7 /// This is a simple extension method that moves to the next 8 /// element of the enumerator, and returns the real value 9 /// instead of a boolean 10 /// </summary> 11 /// <typeparam name="T"></typeparam> 12 /// <param name="enumerator"></param> 13 /// <returns></returns> 14 public static T MoveToNextElement<T>(this IEnumerator<T> enumerator) 15 { 16 // Initialize our return value 17 T nextElement = default(T); 18 T currentElement = enumerator.Current; 19 20 // Try to move to the next element 21 if (enumerator.MoveNext()) 22 { 23 nextElement = enumerator.Current; 24 } 25 else 26 { 27 nextElement = currentElement; 28 } 29 30 return nextElement; 31 32 } // method MoveToNextElement<T> 33 }

    Below is a small usage example:

    1 static void Main(string[] args) 2 { 3 List<int> myInts = new List<int>{ 10, 20, 30, 40, 50 }; 4 5 // Get an enumerator for "myInts" 6 IEnumerator<int> enumerator = myInts.GetEnumerator(); 7 8 Console.WriteLine(enumerator.MoveToNextElement<int>()); 9 Console.WriteLine(enumerator.MoveToNextElement<int>()); 10 Console.WriteLine(enumerator.MoveToNextElement<int>()); 11 Console.WriteLine(enumerator.MoveToNextElement<int>()); 12 } 13

    The output of this sample is shown below:

    10 20 30 40

    The above example also illustrates that extensions methods can be applied to generic types as well as "standard" types. The code for this section can be downloaded from the ExtendInterface project of the download code.

    Extension method restrictions

    The only restriction on extension methods is that they cannot be used to extend a static class, such as System.Math. This makes sense, since a static class cannot be represented by a "this" reference. For example, is you would try to write an extension method for the static System.Math class as shown below:

    1 public static class MathExtension 2 { 3 public static int SumInits(this Math math, int value1, int value2) 4 { 5 return value1 + value2; 6 } 7 }

    You would get the following compilation error:

    Error 1 'System.Math': static types cannot be used as parameters InvalidExtensionMethod

    This is illustrated in the InvalidExtensionMethod project of the download solution.

    Intellisense support for Extension Methods

    Beta2 of Orcas has very nice support for extension method. The extension method is listed as a method of the type, but is adorned with a special icon, and the tooltip includes the fact that it is an extension method, as is shown below:

    Intel99

    Note the small blue "down arrow" icon which indicates an extension method. Also, the tooltip clearly indicates that this method is an extension method by pre-fixing the signature with the (extension) keyword.

    Usage of Extension Methods in LINQ

    All LINQ operators, such as from, where, select etc. are implemented using extension methods. For example, the where clause checks for a boolean result of a test (e.g: Breed == "Great Dane") are implemented as extension methods. We will have more to say about this when we discuss lambda expressions.

    Technorati Tags: , ,
  • New Features in C# 3.0, Part 3: Automatic Properties, Object Initializers and Collection Initializers

    Introduction

    This post does not focus on one particular new feature is the rich new feature set of  C# 3.0, but rather studies a set of features, which are loosely related, and play a roll in the enablement of LINQ in the .NET 3.5 framework, which is ultimately the focus of this series of posts.

    In this post, we will study the following topics:

    1. Automatic properties. Automatic properties allow you to declare class properties using a very terse syntax, increasing your productivity and reducing the amount of  typing that  you have to do.
    2. Object Initializers. Object initializers allow you to use a focused, "short hand" notation to initialize the properties of a class.
    3. Collection Initializers. Like object Initializers allow you to use a "short hand" syntax for the initialization of a class, collection initializers allow you to do the same thing for your collections.

    Previous posts is this series are:

    The code for this feature can be downloaded here.

    Ok enough talk, let's have a look at our first "feature of the day": Automatic Properties!

    Automatic Properties

    Overview

    Note: the code for this feature is contained in the "AutomaticProperties" console application of the code.

     Everybody has written typical "data container" classes before. These are the typical classes which contains simple fields, and properties with both a getter and a setter for each fields. And every develop I know simply HATES writing these things, because they are what I call "monkey code", code that could be written by semi-intelligent primates (or even a project manager ;-).

    Below are some simple examples of such classes:

    1 namespace AutomaticProperties.Classic 2 { 3 /// <summary> 4 /// This is our "classic, old style" CoffeeShop class 5 /// </summary> 6 public class CoffeeShop 7 { 8 private string _shopName; 9 private Address _address; 10 private decimal _priceOfLatte; 11 private string _baristaName; 12 13 public string ShopName 14 { 15 get 16 { 17 return _shopName; 18 } 19 set 20 { 21 _shopName = value; 22 } 23 } 24 25 public Address Address 26 { 27 get 28 { 29 return _address; 30 } 31 set 32 { 33 _address = value; 34 } 35 } 36 37 public Decimal PriceOfLatte 38 { 39 get 40 { 41 return _priceOfLatte; 42 } 43 set 44 { 45 _priceOfLatte = value; 46 } 47 } 48 49 public string BaristaName 50 { 51 get 52 { 53 return _baristaName; 54 } 55 set 56 { 57 _baristaName = value; 58 } 59 } 60 } // class AutomaticProperties.Classic.CoffeeShop 61 } 62

    1 namespace AutomaticProperties.Classic 2 { 3 /// <summary> 4 /// This is our "classic, old style" Address class 5 /// </summary> 6 public class Address 7 { 8 private string _streetName; 9 private int _streetNumber; 10 private string _city; 11 private string _state; 12 private int _zipCode; 13 14 public string StreetName 15 { 16 get 17 { 18 return _streetName; 19 } 20 set 21 { 22 _streetName = value; 23 } 24 } 25 26 public int StreetNumber 27 { 28 get 29 { 30 return _streetNumber; 31 } 32 set 33 { 34 _streetNumber = value; 35 } 36 } 37 38 public string City 39 { 40 get 41 { 42 return _city; 43 } 44 set 45 { 46 _city = value; 47 } 48 } 49 50 public string State 51 { 52 get 53 { 54 return _state; 55 } 56 set 57 { 58 _state = value; 59 } 60 } 61 62 public int ZipCode 63 { 64 get 65 { 66 return _zipCode; 67 } 68 set 69 { 70 _zipCode = value; 71 } 72 } 73 } // class AutomaticProperties.Classic.Address 74

    The code above defines two classes, both of which are in the AutomaticProperties.Classic namespace:

    1. CoffeeShop
    2. Address

    Automatic properties allow you to avoid having to manually declare a private field and write the get/set logic -- instead the compiler will automatically creating the private field and the default get/set operations for you.  Below are the CoffeeShop and Address classes rewritten using Automatic Properties (note that both classes are in the AutomaticProperties.New namespace):

    1 public class CoffeeShop 2 { 3 public string ShopName { get; set; } 4 public Address Address { get; set; } 5 public decimal PriceOfLatte { get; set; } 6 public string BaristaName { get; set; } 7 }

    1 public class Address 2 { 3 public string StreetName { get; set; } 4 public int StreetNumber { get; set; } 5 public string City { get; set; } 6 public string State { get; set; } 7 public int ZipCode { get; set; } 8 }

    That's it. Note that we went from 100+ lines of code to a grand total of 15!

    When the C# 3.0 compiler encounters an empty get/set property implementation like we created above in the CoffeeShop and Address classes, it will now automatically generate a private field for us within our class, and implement a public getter and setter property implementation for it.  The benefit of this is that from a type-contract perspective, the class looks exactly like it did with my first (much more verbose) implementation shown above.  This means that -- unlike resorting to public fields -- I can in the future add validation logic within my property setter implementation without having to change any external component that references my class.

    Usage Example

    Now, using "classic" classes, and classes that use automatic properties is completely identical. To provide this, I have included a small piece of client code in the download file, that looks as follows:

    1 using System; 2 3 // Comment out one of the using statements below 4 // to either use the "Classic" or the "New-Style" 5 // Automatic Properties-style classes 6 7 using AutomaticProperties.Classic; // uses class classes 8 //using AutomaticProperties.New; // uses automatic properties 9 10 namespace AutomaticProperties 11 { 12 class Program 13 { 14 static void Main(string[] args) 15 { 16 Address address = new Address(); 17 address.StreetNumber = 50; 18 address.StreetName = "Passover Lane"; 19 address.ZipCode = 6703; 20 address.State = "MO"; 21 address.City = "Missoula"; 22 23 CoffeeShop coffeeShop = new CoffeeShop(); 24 coffeeShop.Address = address; 25 coffeeShop.PriceOfLatte = 3.95M; 26 coffeeShop.ShopName = "It's a Grind!"; 27 coffeeShop.BaristaName = "6 Shot Lucie"; 28 } 29 } 30 } 31

    You can comment out either the "using AutomaticProperties.Classic" or the "AutomaticProperties.New" line, and depending on which "using" line is not commented out, the code will use  the classic classes, or the classes with the automatic properties. Note though that the rest of code is unchanged.

    There is one interesting thing to try though. If you use the "classic" objects, and you set a breakpoint on a line that sets a property, for example:

    MainBreakPoint

    and you "Step In" (F11), then you will actually go to the setter of the property implementation, as shown below:

    StreetNumberBreak

    this makes sense, since we provided this setter in C#!

    Automatic Properties in detail

    Now, when you switch to the "automatic properties" version of the objects, and you set the same breakpoint and you step in, you notice that nothing actually happens, which makes sense, because there is only direct IL code, generated by the compiler behind the setter implementation, and no C# code, so the compiler has nowhere to go!

    The easiest way to verify this is to bring out our old friend ILDASM.exe, and open our "automatic properties" version Address class is this tool. It would look something like this:

    ILDASM_Address

    now, we can compare this to the "classic" style Address class:

    ILDASM_ADDRESS_Classic

    The we notice that on the surface things very much look the same. Both classes have their properties, and their getters and setters. BUT the big difference is the the "classic" version has the actual fields as we defined them, while for the "automatic properties" version,the compiler injected  a private member variable, prefixed with <k>BackingField, like this one for the City property:

    1 .field private string '<City>k__BackingField' 2 .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )

    The CompilerGeneratedAttribute is useful if you have a tool that would like to find out if something is auto-generated. The getter IL implementation look like this:

    1 .method public hidebysig specialname instance string 2 get_City() cil managed 3 { 4 .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 5 // Code size 11 (0xb) 6 .maxstack 1 7 .locals init (string V_0) 8 IL_0000: ldarg.0 9 IL_0001: ldfld string AutomaticProperties.New.Address::'<City>k__BackingField' 10 IL_0006: stloc.0 11 IL_0007: br.s IL_0009 12 IL_0009: ldloc.0 13 IL_000a: ret 14 } // end of method Address::get_City

    Note the reference to the backing field in line 9. The setter IL looks very similar:

    1 .method public hidebysig specialname instance void 2 set_City(string 'value') cil managed 3 { 4 .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 5 // Code size 8 (0x8) 6 .maxstack 8 7 IL_0000: ldarg.0 8 IL_0001: ldarg.1 9 IL_0002: stfld string AutomaticProperties.New.Address::'<City>k__BackingField' 10 IL_0007: ret 11 } // end of method Address::set_City

    Again note the setting of the backing field at line 9. So, as you can see, the "automatic property" version of the code has NO C# code behind the getters and setters of the properties, which is why we could not step into the code with the debugger.

    One last important note: Automatic properties should have both a getter and a setter. If you leave out one of the two, you will get a compiler error like this:

    Error 1 'AutomaticProperties.New.Address.City.get' must declare a body because it is not marked abstract or extern. Automatically implemented properties must define both get and set accessors.

    When you think about it this really makes sense, the whole concept behind automatic properties is to allow you to quickly write typical "data container" or "property bag" classes, which typically have read/write properties.

    Object Initializers

    Overview

    Note: the code for this feature is contained in the "ObjectInitializers" console application of the code.

     When we write code that deals with simple objects, we tend to rely heavily on the use of properties. The sample code for this section contains a class named "CarModel" which represents the model of a car. The class is shown below:

    1 public class CarModel 2 { 3 private string _make; 4 private string _model; 5 private int _year; 6 7 public string Make 8 { 9 get { return _make; } 10 set { _make = value; } 11 } 12 13 public string Model 14 { 15 get { return _model; } 16 set { _model = value; } 17 } 18 19 public int Year 20 { 21 get { return _year; } 22 set { _year = value; } 23 } 24 25 public override string ToString() 26 { 27 return String.Format( 28 "Make: {0}, Model: {1}, Year: {2} ", Make, Model, Year); 29 } 30 } 31

    In a typical approach, we would initialize a new instance of this class as follows:

    1 private static void CreateCarModelTraditional() 2 { 3 CarModel carModel = new CarModel(); 4 carModel.Make = "Acura"; 5 carModel.Model = "TL"; 6 carModel.Year = 2007; 7 Console.WriteLine("Traditional CarModel: " + carModel); 8 9 } // method CreateCarModelTraditional

    While this is a tried-and-true approach that has served us well for many years, it is very verbose. C# 3.0 now offers a new feature called "Object Initializers", which allows us to write the above code as follows:

    1 private static void CreateCarModelWithInitializer() 2 { 3 CarModel carModel = new CarModel {Make = "Acura", Model = "TL", Year = 2007}; 4 Console.WriteLine("\nCarModel with Initializer: " + carModel); 5 6 } // method CreateCarModelWithInitializer

    All this is is really "Syntactic Sugar", which at the IL level results in the same code as the tradition approach. Indeed, the compiler will automatically generate all of the property-setter code, which has exactly the same implementation as our first, more verbose example (more in on this in our "In-Depth" section).

    Note that Object Initializers will also work with more complex objects, which have nested sub-objects. For example, below is the code for a "Car" class, which contains an embedded "CarModel" instance:

    1 public class Car 2 { 3 public CarModel CarModel { get; set; } 4 public int EngineCC { get; set; } 5 public int HoursePower { get; set; } 6 public string Color { get; set; } 7 8 public override string ToString() 9 { 10 return String.Format( 11 "Make: {0}, Model: {1}, Year: {2}, \n\tEngineCC: {3}, HorsePower: {4}, Color: {5}", 12 CarModel.Make, CarModel.Model, CarModel.Year, EngineCC, HoursePower, Color); 13 } 14 }

    Note that is this case, I used the more compact "Automatic Properties" approach described in the first part of this post . Indeed Object Initializers work directly with the property setters, so they don't know or care that you used the traditional approach, or the "Automatic Properties" approach to create your properties.

    Below is an example of an object initializer for a Car instance:

    1 private static void createCompoundObject() 2 { 3 // Create a Car instance with an initializer 4 Car car = new Car { 5 Color = "White", 6 HoursePower = 320, 7 EngineCC = 3600, 8 CarModel = new CarModel {Make = "Acura", Model = "TL Type S", Year = 2007}}; 9 10 Console.WriteLine("\nComplete Car With Initializer: " + car + Environment.NewLine); 11 12 } // method createCompoundObject

    In line 8, you can see how we embedded the initializer for the CarModel directly into the initializer for the Car instance.

    Object Initializers in depth

    In this section, we  will look at the code that is generated by the compiler when we write an object initializer. For example, is we pull out ILDASM (yes, always have that one on your tool belt ;-), and look at the code for the method CreateCarModelWithInitializer(), we see the following:

    1 .method private hidebysig static void CreateCarModelWithInitializer() cil managed 2 { 3 // Code size 63 (0x3f) 4 .maxstack 2 5 .locals init ([0] class ObjectInitializers.CarModel carModel, 6 [1] class ObjectInitializers.CarModel '<>g__initLocal0') 7 IL_0000: nop 8 IL_0001: newobj instance void ObjectInitializers.CarModel::.ctor() 9 IL_0006: stloc.1 10 IL_0007: ldloc.1 11 IL_0008: ldstr "Acura" 12 IL_000d: callvirt instance void ObjectInitializers.CarModel::set_Make(string) 13 IL_0012: nop 14 IL_0013: ldloc.1 15 IL_0014: ldstr "TL" 16 IL_0019: callvirt instance void ObjectInitializers.CarModel::set_Model(string) 17 IL_001e: nop 18 IL_001f: ldloc.1 19 IL_0020: ldc.i4 0x7d7 20 IL_0025: callvirt instance void ObjectInitializers.CarModel::set_Year(int32) 21 IL_002a: nop 22 IL_002b: ldloc.1 23 IL_002c: stloc.0 24 IL_002d: ldstr "\nCarModel with Initializer: " 25 IL_0032: ldloc.0 26 IL_0033: call string [mscorlib]System.String::Concat(object, 27 object) 28 IL_0038: call void [mscorlib]System.Console::WriteLine(string) 29 IL_003d: nop 30 IL_003e: ret 31 } // end of method Program::CreateCarModelWithInitializer 32

    Now, when we compare this code with the code for the CreateCarModeTraditional():

    1 .method private hidebysig static void CreateCarModelTraditional() cil managed 2 { 3 // Code size 61 (0x3d) 4 .maxstack 2 5 .locals init ([0] class ObjectInitializers.CarModel carModel) 6 IL_0000: nop 7 IL_0001: newobj instance void ObjectInitializers.CarModel::.ctor() 8 IL_0006: stloc.0 9 IL_0007: ldloc.0 10 IL_0008: ldstr "Acura" 11 IL_000d: callvirt instance void ObjectInitializers.CarModel::set_Make(string) 12 IL_0012: nop 13 IL_0013: ldloc.0 14 IL_0014: ldstr "TL" 15 IL_0019: callvirt instance void ObjectInitializers.CarModel::set_Model(string) 16 IL_001e: nop 17 IL_001f: ldloc.0 18 IL_0020: ldc.i4 0x7d7 19 IL_0025: callvirt instance void ObjectInitializers.CarModel::set_Year(int32) 20 IL_002a: nop 21 IL_002b: ldstr "Traditional CarModel: " 22 IL_0030: ldloc.0 23 IL_0031: call string [mscorlib]System.String::Concat(object, 24 object) 25 IL_0036: call void [mscorlib]System.Console::WriteLine(string) 26 IL_003b: nop 27 IL_003c: ret 28 } // end of method Program::CreateCarModelTraditional 29

    We note the the ONLY difference between the generated IL is the following:

    .locals init ([0] class ObjectInitializers.CarModel carModel, [1] class ObjectInitializers.CarModel '<>g__initLocal0')

    The second line in this code block is some bookkeeping for the compiler to remember that  Object Initializers were used for this code, but for the rest the code is identical, and the total size of the the general IL is almost the same (61 and 63 bytes), so there is really no overhead in using object initializers.

    One case where you need to pay a bit of attention is if you have any object that has a non-default constructor, as show in the example below:

    1 public class Engine 2 { 3 public int Horsepower { get; set; } 4 public int CC { get; set; } 5 6 public Engine(int horsePower) 7 { 8 Horsepower = horsePower; 9 } 10 } // class Engine 11

    If you would attempt to use an object initializer in this scenario like this, you will run into some problems:

    1 private static void objectWithCtorExample() 2 { 3 Engine engine = new Engine { Horsepower = 120, CC = 2600 }; 4 }

    Indeed, you will get the following compilation error:

    Error 1 'ObjectInitializers.Engine' does not contain a constructor that takes '0' arguments

    You have two solutions for this:

    1. Add a default constructor to your class (in all  of our previous examples, this default constructor was automatically written for us by the compiler).
    2. Use a syntax that uses the constructor, and uses an object initializer for the remaining properties, as is show below:

    1 private static void objectWithCtorExample() 2 { 3 Engine engine = new Engine(120) { CC = 2600 }; 4 }

    SO, the above code is a bit of a "hybrid" (to use a popular expression -) between the use of constructors and object initializers.

    Collection Initializers

    Overview

    Note: the code for this feature is contained in the "CollectionInitializers" console application of the code.

    The concept of Object Initializers can be expanded to collections with C# 3.0. Using a new feature, called "Collection Initializers" you an use a compact syntax to initialize a collection.

    For example, take the following class:

    1 public class Dog 2 { 3 public string Breed { get; set; } 4 public string HairColor { get; set; } 5 public int Weight { get; set; } 6 public bool IsFriendly { get; set; } 7 8 public override string ToString() 9 { 10 return String.Format("\tDog: Breed: {0}, HairColor: {1}, Weight : {2}, IsFriendly: {3}", 11 Breed, HairColor, Weight, IsFriendly); 12 } 13 } // class Dog

    in a traditional approach, you could create a collection of dogs as follows:

    1 private static void createDogListTraditional() 2 { 3 List<Dog> dogs = new List<Dog>(); 4 dogs.Add(new Dog {Breed = "Great Dane", HairColor = "Fawn", Weight = 165, IsFriendly = true}); 5 dogs.Add(new Dog { Breed = "Mud", HairColor = "DirtyBlack", Weight = 15, IsFriendly = false }); 6 7 } // method createDogListTraditional 8

    So, here we do what we always do, we create a collection, and then add new instances to the collection. The approach with a collection initializer results in more compact code, as is shown below:

    1 private static void createDogListCollectionInitializer() 2 { 3 List<Dog> dogs = new List<Dog>() { 4 new Dog { Breed = "Great Dane", HairColor = "Fawn", Weight = 165, IsFriendly = true }, 5 new Dog { Breed = "Mud", HairColor = "DirtyBlack", Weight = 15, IsFriendly = false } 6 }; 7 8 } // method createDogListCollectionInitializer 9

    So, we no longer need the "dogs.Add", statements, and our code looks more natural and compact.

    Collection Initializers in depth

    I looked at the generated IL code in ILDASM, and the code sizes for each of the methods was as follows:

    • CreateDogListTraditional(): 128 bytes
    • CreateDogListCollectionInitializer(): 130 bytes

    So again, there is no noticeable overhead in using collection initializers in your code, and I would greatly recommend that you do so to improve the readability of your code.

    Conclusion

    I hope this article provided you with a good overview of automatic properties, object initializers and collection initializers. These 3 features are used in every LINQ query, and are actually also very useful when you are writing regular production code.

    In our next post, we will look at C# 3.0 lambda expressions, which go directly to the core of the how LINQ expressions are generated by the compiler.

    Technorati Tags: ,
Copyright ASIQS Corporation © 2006, All rights reserved.
Powered by Community Server (Commercial Edition), by Telligent Systems