Wait! Don’t freak out. The point of this post is demystify all of this craziness. So there are 3 related concepts that we need to talk about: delegates, anonymous delegates, and lambda expressions.
Delegates:
Delegates are basically a signature of what a method is supposed to look like – AND it can keep track of all of the implementations of it as well. You already know delegates if you are familiar with events in windows programming. So for example, we might define a delegate like this:
delegate string MakeStringsBetterDelegate(string input);
This says we a delegate with a return type of string, and it takes in 1 argument of type string. Next, we can create an implementation of this delegate by doing something like this:
public string MakeStringsBetterImplementation(string input)
{
return input += "_MakingTheStringBetter!";
}
Anonymous Delegates:
Now the next step is we can shorten this a little bit. Instead of having an explicit implementation, we can define it on-the-fly with an anonymous delegate. It’s called anonymouse, because it’s not a named function:
MakeStringsBetterDelegate betterDelegate = delegate(string input)
{
return input += "_MakingTheStringBetter!";
};
So this does the same thing, except instead of explicitly defining the implementation, we do it dynamically. To run this delegate, we can now do something like this:
// Returns "Hello_MakingTheStringBetter!"
string ouput = betterDelegate("Hello");
Lambda Expresisons:
So lastly, in .NET 3.5 and greater, there is this notion of lambda expressions, which takes this to the next level. To re-write the anonymous method, we could now do this:
MakeStringsBetterDelegate betterer = input =>
{ return input += "_MakingTheStringBetter!"; };
Now, this is where I got stumped. I didn’t really understand the syntax. So let me try to explain the way I understand (and think is correct). "input" is a placeholder for the input argument, and the rest is the same. In fact, this same line can be expressed in a few different acceptable ways. To help clear up the "input" part, this may help – you can also define it like this:
MakeStringsBetterDelegate betterer = (string input) =>
{ return input += "_MakingTheStringBetter!"; };
Now, the next clumsy thing is the fact that we still have to define that delegate. Well, in .NET 3.5 – there are some helper delegates that handle this need. For example, you can use the Func<T> delegate:
Func<string, string> betterer = (string input) =>
{ return input += "_MakingTheStringBetter!"; };
The first argument is the input data type, and the second argument is the return data type. So basically, when you call "betterer", you pass it in a string, it’s going to add on "_MakingTheStringBetter", and return that as a return value. Here is another example:
Func<string,bool> isBetter = input => input.Contains("_MakingTheStringBetter");
So this defines a dynamic delegate (using Func<T>) – that has a string input and returns a bool. This expression returns a true, if the string that was passed in (input) contains "_MakingTheStringBetter". In other words, you could consume this expression like this:
bool isAlreadyBetterer = isBetter(someString);
As I’ve been learning Linq, these lambda expressions were really jamming me up. So hopefully this helps someone else – and I can tell you, it will help me later when I forget all these details, but I can just go back to this post. 🙂
Leave a Reply