These days we see a lot of Lambda expressions popping up in code. Lambda expressions are indeed a great way of defining and passing “method information” to other classes and methods. I define them as “method information”, because there are in fact a couple of .NET types that accept a lambda expression as their value.
As an example I want to pass method information about a method, which accepts a string as input parameter and returns a number, as a parameter for another method.
The invocation of this method can look like this:
MethodInvoker.GiveMeTheMethod((s) => s.Length);
But which type can we use for the parameter of this method?
Define the parameter as a specific delegate
The most traditional way of defining the type of the parameter is to create a specific delegate:
public delegate int TheMethod(string parameter); public static void GiveMeTheMethod(TheMethod theMethod) { int result = theMethod("some string"); }
Define the parameter as a Func Type
Defining specific delegates can be timeconsuming.
Since .NET 3.5 we can make use of Func. This generic type can be used to define a delegate which can accept up to 8 parameters and off course one return type (for void delegates you should use the Action delegate).
The implementations of the method can look like this:
public static void GiveMeTheMethod(Func<string,int> theMethod) { int result = theMethod("some string"); }
Define the parameter as an Expression Tree
I will not go in detail on Expression Trees. You can read a lot of articles about this already.
If we define the method parameter as an Expression type, the method definition could look like this:
public static void GiveMeTheMethod(Expression<Func<string, int>> theMethod) { int result = theMethod.Compile()("some string"); }
You just wrap the Func delegate in an Expression object (you could also pass a specific delegate off course).
The Compile method converts the Expression Tree to a delegate, which we can invoke.
So, why should we use an Expression Tree? There are probably a lot of reasons, but for me the following 2 reasons are the most important.
- You want to get the name of the method or property, which is used in the lambda expression without executing it. This is used to implement a type safe PropertyChanged notification method.
On an Expression type you can call the Name property to achieve this information. - If you have a reference in to the input argument of your method, but the argument is not yet instantiated at that moment, you have to use an Expression Tree. If you use a delegate type, this will throw a null reference exception, because it expects an instance of the object to retrieve the pointer to the method of this object.