Ok, for clarity I'm going to write the two out again (and slightly modify the method to make it shorter)
public static Func<HtmlHelper, PropertyViewModel, string> RenderDelegate = (a, b) =>
{
return a.RenderPartial(b);
};
public static string RenderMethod(HtmlHelper a, PropertyViewModel b)
{
return a.RenderPartial(b);
}
Firstly note that RenderDelegate
is (as S. DePouw writes), just a fancy way of using lambda syntax to write the following:
public static Func<HtmlHelper, PropertyViewModel, string> RenderDelegate =
delegate(HtmlHelper a, PropertyViewModel b)
{
return a.RenderPartial(b);
};
The difference between RenderMethod
and RenderDelegate
is that RenderMethod
is a method, wheras RenderDelegate
is a delegate, or more specifically a field of type Delegate. This means that RenderDelegate can be assigned to.
What is a Delegate?
A delegate is a type. From the MSDN documentation:
A delegate is a type that defines a method signature, and can be associated with any method with a compatible signature.
Essentially you can think of a delegate as a reference / pointer to a method, however the method that the delegate points to has to match the signature that the delegate is expecting. So for example Func<HtmlHelper, PropertyViewModel, string>
is a Delegate that expects methods with the signature string MyMethod(HtmlHelper, PropertyViewModel)
and so we are able to assign methods with that signature to that delegate like this:
RenderDelegate = RenderMethod;
Its important to note the difference between the Delegate type (note the capital D) and the delegate keyword (lower case d). In your example your using the Func<>
generic object to condense your code, however its kind of obscuring whats really going on here. Func<HtmlHelper, PropertyViewModel, string>
is a type which inherits from Delegate
, and you could use the delegate keyword to delcare an equivalent type:
delegate string MyFunction<HtmlHelper helper, PropertyViewModel string>;
static MyFunction RenderDelegate = RenderMethod;
Anonymous methods
When we assigned RenderDelegate in the first example, we didnt set RenderDelegate to an existing named method, instead we declared a new method in-line. This is known as an Anonymous Method and works because we are able to pass a code block (also declared using the delegate keyword) as a delegate parameter:
Lambda functions
Back to the original syntax - your example is using lambda syntax to delcare an anonymous delegate in a funny way. Lambda expressions are good way of declaring short inline methods which might commonly be used when dealing with lists, for example supposing we want to sort a list of HtmlHelper objects by their Name. The way of doing this is to pass a Delegate that compares two HtmlHelper objects to the lists Sort method, the sort method then uses that delegate to compare and sort the elements in the list:
static int MyComparison(HtmlHelper x, HtmlHelper y)
{
return x.Name.CompareTo(y.Name);
}
static void Main()
{
List<HtmlHelper> myList = GetList();
myList.Sort(MyComparison);
}
To avoid having loads of short methods scattered around, you can use anonymous methods to delcare the sorting method in-line. Whats also really useful about this is that the in-line method has access to variables declared in the containing scope:
int myInt = 12;
List<HtmlHelper> myList = GetList();
myList.Sort(
delegate (HtmlHelper x, HtmlHelper y)
{
return x.Name.CompareTo(y.Name) - myInt;
});
Thats still fairly quite a lot of typing however, and so the lambda sytax was born and now you can do this instead:
List<HtmlHelper> myList = GetList();
myList.Sort((x, y) => {return x.Name.CompareTo(y.Name)});
Declaring "normal" methods in this way however seems to be completely pointless to me (and makes my eyes bleed)
Delegates are incredibly useful and are (among other things) the cornerstone of the .Net event system. Some more reading to clear things up a bit: