This question already has an answer here:
Can anyone provide a concise distinction between anonymous method and lambda expressions?
Usage of anonymous method:
private void DoSomeWork()
{
if (textBox1.InvokeRequired)
{
//textBox1.Invoke((Action)(() => textBox1.Text = "test"));
textBox1.Invoke((Action)delegate { textBox1.Text = "test"; });
}
}
Is it only a normal lambda expression being cast to a strongly typed delegate or there is more of it undercover.
I'm well aware that a strongly typed delegate like follow
UpdateTextDelegate mydelegate = new UpdateTextDelegate(MethodName)
suffice as a parameter of type System.Delegate
, but the idea of anonymous method is rather new to me.
To be precise, what you name 'anonymous delegate' is actually an anonymous method.
Well, both lambdas and anonymous methods are just syntax sugar. The compiler will generate at least a 'normal' method for you, although sometimes (in the case of a closure) it will generate a nested class with the no-longer-anonymous method in it.
What is an anonymous method? Is it really anonymous? Does it have a name? All good questions, so let's start with them and work our way up to lambda expressions as we go along.
When you do this:
What actually happens?
The compiler first decides to take the "body" of the method, which is this:
and separate out that into a method.
Two questions the compiler now has to answer:
The second question is easily answered. The
delegate {
part answers that. The method takes no parameters (nothing betweendelegate
and{
), and since we don't care about its name (hence the "anonymous" part), we can declare the method as such:But why did it do all this?
Let's look at what a delegate, such as
Action
really is.A delegate is, if we for a moment disregard the fact that delegates in .NET are actually linked list of multiple single "delegates", a reference (pointer) to two things:
So, with that knowledge, the first piece of code could actually be rewritten as this:
Now, the problem with this is that the compiler has no way of knowing what
Test
actually does with the delegate it is given, and since one half of the delegate is a reference to the instance on which the method is to be called,this
in the above example, we don't know how much data will be referenced.For instance, consider if the above code was part of a really huge object, but an object that only live temporarily. Also consider that
Test
would store that delegate somewhere it would live for a long time. That "long time" would tie itself up to the life of that huge object as well, keeping a reference to that for a long time as well, probably not good.So the compiler does more than just create a method, it also creates a class to hold it. This answers the first question, where should I put it?.
The code above can thus be rewritten as follows:
That is, for this example, what an anonymous method is really all about.
Things get a bit more hairy if you start using local variables, consider this example:
This is what happens under the hood, or at least something very close to it:
The compiler creates a class, lifts all the variables that the method requires into that class, and rewrites all access to the local variables to be access to fields on the anonymous type.
The name of the class, and the method, are a bit odd, let's ask LINQPad what it would be:
If I ask LINQPad to output the IL (Intermediate Language) of this program, I get this:
Here you can see that the name of the class is
UserQuery+<>c__DisplayClass1
, and the name of the method is<Main>b__0
. I edited in the C# code that produced this code, LINQPad doesn't produce anything but the IL in the example above.The less-than and greater-than signs are there to ensure that you cannot by accident create a type and/or method that matches what the compiler produced for you.
So that's basically what an anonymous method is.
So what is this?
Well, in this case it's the same, it's a shortcut for producing an anonymous method.
You can write this in two ways:
In its first form you can write all the code you would do in a normal method body. In its second form you're allowed to write one expression or statement.
However, in this case the compiler will treat this:
the same way as this:
They're still anonymous methods, it's just that the
() =>
syntax is a shortcut to getting to it.So if it's a shortcut to getting to it, why do we have it?
Well, it makes life a bit easier for the purpose of which it was added, which is LINQ.
Consider this LINQ statement:
This code is rewritten as follows:
If you were to use the
delegate { ... }
syntax, you would have to rewrite the expressions withreturn ...
and so on, and they'd look more funky. The lambda syntax was thus added to make life easier for us programmers when writing code like the above.So what are expressions?
So far I have not shown how
Test
has been defined, but let's defineTest
for the above code:This should suffice. It says that "I need a delegate, it is of type Action (taking no parameters, returning no values)".
However, Microsoft also added a different way to define this method:
Note that I dropped a part there, the
....
part, let's get back to that 1.This code, paired with this call:
will not actually pass in a delegate, nor anything that can be called (immediately). Instead, the compiler will rewrite this code to something similar (but not at all like) the below code:
Basically the compiler will build up an
Expression<Func<...>>
object, containing references to the variables, the literal values, the operators used, etc. and pass that object tree to the method.Why?
Well, consider the
db.Customers.Where(...)
part above.Wouldn't it be nice if, instead of downloading all customers (and all their data) from the database to the client, looping through them all, finding out which customer has the right name, etc. the code would actually ask the database to find that single, correct, customer at once?
That's the purpose behind expression. The Entity Framework, Linq2SQL, or any other such LINQ-supporting database layer, will take that expression, analyze it, pick it apart, and write up a properly formatted SQL to be executed against the database.
This it could never do if we were still giving it delegates to methods containing IL. It can only do this because of a couple of things:
Expression<Func<...>>
is limited (no statements, etc.)So, let's summarize:
Footnotes:
The
....
part for such a simple expression is meant for the type of return value you get from the expression. The() => ... simple expression ...
only allows expressions, that is, something that returns a value, and it cannot be multiple statements. As such, a valid expression type is this:Expression<Func<int>>
, basically, the expression is a function (method) returning an integer value.Note that the "expression that returns a value" is a limit for
Expression<...>
parameters or types, but not of delegates. This is entirely legal code if the parameter type ofTest
is anAction
:Obviously,
Debug.WriteLine("Test")
doesn't return anything, but this is legal. If the methodTest
required an expression however, it would not be, as an expression must return a value.There is one subtle difference you should be aware of. Consider the following queries (using the proverbial NorthWind).
The first one uses an anonymous delegate and the second one uses a lambda expression. If you evaluate the results of both you will see the same thing. However, looking at the generated SQL, we'll see quite a different tale. The first generates
Whereas the second generates
Notice in the first case, the where clause is not passed to the database. Why is this? The compiler is able to determine that the lambda expression is a simple single-line expression which can be retained as an expression tree, whereas the anonymous delegate is not a lambda expression and thus not wrappable as an
Expression<Func<T>>
. As a result in the first case, the best match for the Where extension method is the one that extends IEnumerable rather than the IQueryable version which requires anExpression<Func<T, bool>>
.At this point, there's little use to the anonymous delegate. It's more verbose and less flexible. In general, I would recommend always using the lambda syntax over the anonymous delegate syntax and pick up parsability and syntactic terseness as well.