Question

I have stolen seen the following code from the interwebs. Method signarure is

public static MvcHtmlString RecordPager(this HtmlHelper html, PagingInfoModel pageInfo, Func<int,string> someUrl )

This gets called in the View as follows:

@Html.RecordPager(Model.PagingInfoModel, x => Url.Action("Index", new { page = x }) )

My question is specifically about the last parameter, i don't quite understand how can you pass the argument x => Url.Action("Index", new { page = x }) into the parameter

Func<int,string> someUrl

I know this is an Extension method for MVC's HtmlHelper, etc. and Func<int, string> is a delegate expecting an int and returning a string, but where is the int in the argument x => Url.Action etc...

You may have gathered i don't understand lamba and linq and anonymous functions and all that modern jazz, but please provide a decent explanation for dummies like me who will encounter this same question. Thanks.

Was it helpful?

Solution

A Func<int, string> is basically a delegate with the following signature:

public delegate string Func(int I)

Prior to C# 2, The only way to pass a method to a delegate (which is a pointer to a function) was to explicitly create a named method with the same signature as the delegate above, like the following:

public string MyAwsomeFunc(int I)

And that method could be passed to a method containing the delegate as a parameter:

public void SomeFunc(Func callback)

C# 2 introduced Annonymous Methods, which enabled us to create delegate handlers "on the fly", letting the compiler create the named method for us:

// Create a delegate. 
delegate string Func(int x);

// Instantiate the delegate using an anonymous method.
Func d = delegate(int k) { /* ... */ };

C# 3 introduced us to Lamba Expressions, which is the preferred way of handling delegates in C#. A lambda expression is an anonymous method that you can use to create a delegate. By using lambda expressions, you can write local functions that can be passed as arguments or returned as the value of function calls:

delegate int del(int i);

del myDelegate = x => x * x // lamba expression syntax
int j = myDelegate(5); //j = 25

What happened in your method is that it accepts a delegate type of Func<int, string>, and using the lamba expression syntax:

 x => Url.Action("Index", new { page = x }) )

x is the input parameter for Func, which is an int and is being assigned to the page property, and the Url.Action method returns a string, which is what the return type is expected to be. The compiler is doing the work of generating a delegate handler for us, so we dont have to. It would be the same as using the following approach with a named method:

string MyMethod(int I)
{
    string result = Url.Action("index", new { page = I });
    return result;
}

Then, sending MyMethod as a parameter:

@Html.RecordPager(Model.PagingIngModel, MyMethod(someInt));

Edit

Some reading material:

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top