So when I write something like this
Action action = new Action(()=>_myMessage = "hello");
Refactor Pro! Highlights this as a redundant delegate creation and allows me to to shorten it to
Action action = () => _myMessage="hello";
And this usually works great. Usually, but not always. For example, Rhino Mocks has an extension method named Do:
IMethodOptions<T> Do(Delegate action);
Here, passing in the first version works, but the second doesn't. What exactly is going on under the covers here?
They are actually two very different things. "Delegate" is actually the name for a variable that holds a reference to a method or a lambda, and a lambda is a method without a permanent name. Lambdas are very much like other methods, except for a couple subtle differences.
Lambda expressions in C# are used like anonymous functions, with the difference that in Lambda expressions you don't need to specify the type of the value that you input thus making it more flexible to use. The '=>' is the lambda operator which is used in all lambda expressions.
Advertisements. The term 'Lambda expression' has derived its name from 'lambda' calculus which in turn is a mathematical notation applied for defining functions. Lambda expressions as a LINQ equation's executable part translate logic in a way at run time so it can pass on to the data source conveniently.
A lambda expression is a short block of code which takes in parameters and returns a value. Lambda expressions are similar to methods, but they do not need a name and they can be implemented right in the body of a method.
The first version is effectively doing:
Action tmp = () => _myMessage = "hello"; var action = new Action(tmp);
The problem you're running into is that the compiler has to know what kind of delegate (or expression tree) the lambda expression should be converted into. That's why this:
var action = () => _myMessage="hello";
actually doesn't compile - it could be any delegate type with no parameters and either no return value or the same return type as _myMessage
(which is presumably string
). For instance, all of these are valid:
Action action = () => _myMessage="hello"; Func<string> action = () => _myMessage="hello"; MethodInvoker action = () => _myMessage="hello"; Expression<Action> = () => _myMessage="hello"; // etc
How could the C# compiler work out what type action
was meant to be, if it were declared with var
?
The simplest way to get round this when calling a method (for your Rhino Mocks example) is to cast:
methodOptions.Do((Action) (() => _myMessage = "hello"));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With