2011-03-15 12 views
39

Estoy leyendo el libro Pro MVC 2, y hay un ejemplo de cómo crear un método de extensión para la clase HtmlHelper.¿Alguien puede explicar lo que hace el C# "Func <T,T>"?

Aquí el ejemplo de código:

public static MvcHtmlString PageLinks(this HtmlHelper html, PagingInfo pagingInfo, Func<int,string> pageUrl) 
{ 
    //Magic here. 
} 

Y aquí es un ejemplo de uso:

[Test] 
public void Can_Generate_Links_To_Other_Pages() 
{ 
    //Arrange: We're going to extend the Html helper class. 
    //It doesn't matter if the variable we use is null    
    HtmlHelper html = null; 

    PagingInfo pagingInfo = PagingInfo(){ 
     CurrentPage = 2, 
     TotalItems = 28, 
     ItemsPerPage = 10 
    }; 

    Func<int, String> pageUrl = i => "Page" + i; 

    //Act: Here's how it should format the links. 
    MvcHtmlString result = html.PageLinks(pagingInfo, pageUrl); 

    //Assert: 
    result.ToString().ShouldEqual(@"<a href=""Page1"">1</a><a href=""Page2"">2</a><a href=""Page3"">3</a>")   

} 

Editar: parte retirada que confundió el puntode esta pregunta.

La pregunta es: ¿Por qué el ejemplo usa Func? ¿Cuándo debería usarlo? ¿Qué es Func?

Gracias!

+0

Principalmente, me gustaría saber cuál es el Func PAGEURL = i => "Page1" + i; línea está haciendo. –

+1

No entiendo. 'Func ' no tiene nada que ver con los métodos de extensión. ¿Que estas preguntando? – BoltClock

+0

¿Te refieres a la declaración de 'PageLinks'? El primer parámetro es 'this', es decir, es un método de extensión. Ese parámetro se une al objeto 'html' en la llamada. – Pete

Respuesta

105

Un Func<int, string> como

Func<int, String> pageUrl = i => "Page" + i; 

es un delegado aceptar int como único parámetro y devolver un string. En este ejemplo, acepta un parámetro int con el nombre i y devuelve la cadena "Page" + i que acaba de concatenar una cadena de representación estándar de i a la cadena "Page".En general, Func<TSource, TResult> acepta un parámetro que es del tipo TSource y devuelve un parámetro del tipo TResult. Por ejemplo,

Func<string, string> toUpper = s => s.ToUpper(); 

entonces se puede decir

string upper = toUpper("hello, world!"); 

o

Func<DateTime, int> month = d => d.Month; 

por lo que se puede decir

int m = month(new DateTime(3, 15, 2011)); 
1

Porque el método PageLinks es Extension Method.

En el método de extensión, el primer parámetro comienza con esta palabra clave para indicar que se trata de un método de extensión en el tipo representado por el primer parámetro.

El Func<T1, T2> es un delegado que representa una transformación del tipo T1 al tipo T2. Entonces, básicamente, su método PageLinks aplicará esa transformación a int para producir un string.

+1

Ok, pero ¿qué pasa con la parte de Func? –

+0

Ver mi respuesta para el enlace a Func. –

13

Func<int, String> significa un método de devolución de llamada que toma un parámetro int y devuelve un String como resultado.

La siguiente expresión, que se conoce como un lambda expression:

Func<int, String> pageUrl = i => "Page" + i; 

amplía a algo como esto:

Func<int, String> pageUrl = delegate(int i) 
{ 
    return "Page" + i; 
} 
3

La línea Func<int, string> que se pide información sobre que se conoce como una expresión lambda.

Func<int, String> pageUrl = i => "Page" + i; 

Esta línea puede ser descrita como una función que toma un parámetro int (i) y devuelve una cadena "Page" + i;

Se puede volver a escribir como:

delegate(int i) 
{ 
    return "Page" + i; 
} 
+0

¿Es posible sobrecargar delegados, digamos si la entrada era una T genérica donde T: clase? –

1

Func<T, TResult>: Encapsula un método que tiene un parámetro y retornar ns un valor del tipo especificado por el parámetro TResult. See this page for more details y ejemplos. :-)

0

he implementado un método de extensión, donde() usando Func por favor una mirada ...

public static IEnumerable<Tsource> Where<Tsource> (this IEnumerable<Tsource> a , Func<Tsource , bool> Method) 
{ 

    foreach (var data in a) 
    { 
     //If the lambda Expression(delegate) returns "true" Then return the Data. (use 'yield' for deferred return) 
     if (Method.Invoke (data)) 
     { 
      yield return data; 
     } 
    } 
} 

Se puede utilizar como,

 foreach (var item in Emps.Where (e => e.Name == "Shiv").Select (e1 => e1.Name)) 
     { 
      Console.WriteLine (item); 
     } 
1

Tener un blog el esta. Usando Func puede resolver algunas de las discrepancias funcionales. Lee here.

0

Crear su propio

Func<int,string> myfunc; 

continuación, haga clic derecho Func para ver la definición. Usted verá que es un delegado underneith

public delegate TResult Func<in T, out TResult>(T arg); 
Cuestiones relacionadas