2012-04-10 12 views
43

Soy bastante nuevo en C# y MVC y he usado lambdas en ciertas ocasiones, como para métodos anónimos y en LINQ.Quiero entender la expresión lambda en @ Html.DisplayFor (modelItem => item.FirstName)

Por lo general ver las expresiones lambda que se ven algo como esto:

(x => x.Name), (x => { Console.WriteLine(x)) 

entiendo que lambda = "va a". Nunca he visto una expresión lambda donde el parámetro izquierdo no se usa.

No sé cómo traducir esta expresión lambda aunque

@Html.DisplayFor(modelItem => item.FirstName) 

¿Alguien puede arrojar algo de luz sobre esto para mí? No debería ser esto

(modelItem => modelItem.FirstName)? 

llegué esto desde Microsoft de Introduction to ASP.NET MVC tutorial.

+0

¿Ha probado que la aplicación? ¿Funciona? Sería bueno utilizar la notación de puntos de esa manera, tenía la impresión de que solo se podía acceder a través de índices. –

+0

sí, es lo que veo ver en los tutoriales y lo he estado haciendo yo mismo por un tiempo. Sin embargo, siempre me he preguntado por qué no modelItem => modelItem.FirstName ... también lo intenté y no funcionó. Sí, sería mucho mejor usar notación de puntos. A mi me parece un "truco" en cierto modo. Espero que la notación de puntos sea posible en el futuro ... –

+0

Según el enlace de 'GraemeMiller', una forma más adecuada sería' @ Html.DisplayFor ((= = item.FirstName) ' –

Respuesta

89

Una expresión lambda es una forma de escribir una función anónima, es decir, una función sin nombre. Lo que tienes en el lado izquierdo de la "flecha" son los parámetros de la función, y lo que tienes en el lado derecho es el cuerpo de la función. Por lo tanto, (x => x.Name) se traduce lógicamente a algo así como string Function(Data x) { return x.Name }, los tipos string y Data obviamente variarán y se derivarán del contexto.

La ausencia del parámetro del lado izquierdo se traduce en una función sin parámetros, por lo que este (() => someVariable) traduce lógicamente a esto: string Function() { return someVariable; }

En este punto es posible que empezar a preguntarse, donde someVariable proviene, no es una función parámetro y no está definido en la función. Estaría en lo cierto, una función como esta nunca compilaría. Sin embargo, la función lambda como esta está perfectamente bien, ya que permite levantar variables de alcance externo y usarlas de esta manera. (Internamente, se crea una clase contenedora donde las variables que se usan en la expresión lambda se convierten en campos).

Ahora veamos qué significa model => item.FirstName. Lógicamente se traduciría a string Function(Model model) { return item.FirstName; }. Básicamente esta es una función con un parámetro, pero este parámetro no se usa.

Y ahora, el último bit de la información. Aunque las expresiones lambda representan funciones al final, a veces se crean no con el propósito de ser realmente ejecutadas (aunque potencialmente pueden). Una expresión lambda se puede representar en la forma de un árbol de expresión. Esto significa que en lugar de ejecutarlo puede ser analizado.

En este caso particular, el motor MVC no ejecuta la función que representa la expresión lambda. En cambio, la expresión es analizada para que el motor MVC sepa qué html debe emitir para esta línea en particular. Si su elemento de datos no proviene directamente de su objeto modelo, la parte izquierda de la expresión lambda no tiene importancia.

+0

Gran explicación. Mi respuesta sin duda debe ser desmarcada para esta bien escrita :) – GraemeMiller

+0

@GraemeMiller sí, creo que este tipo merece mucho crédito y respeto por su arduo trabajo. Gracias. Definitivamente una respuesta muy hermosa con respecto a lambda, motor MVC y lambdas sin parámetros en general :) –

+3

@zespri Muchas gracias por la respuesta. Definitivamente una completa y respondió mis curiosidades inconscientes sobre lambdas y el motor de mvc :) –

4

Está utilizando una lambada sin parámetros. Ver esto question

Básicamente DisplayFor no utiliza el modelo de parámetros de la función lambda (podría ser cualquier cosa que diría usar _ o()) y simplemente usa la función lambda dentro del bucle for para usar displayfor en su contra. DisplayFor requiere una función lambda.

6

Creo que se trata del ciclo foreach. ejemplo:

@foreach(var item in model) 
{ 
<td> 
    @html.displayfor(model => item.firstName) </td> 
</td>  
} 

var item necesita ser utilizado debido a que cada elemento de la secuencia es un tipo anónimo. model => item.firstName significa (input parameter) => expression. no puede usar el parámetro de entrada porque almacenamos el "elemento" actual en item.

+0

¡Gracias! Después de leer la respuesta principal (hermosa pero bastante abstracta), esto me ayudó a aclararla de una manera más práctica para mi cerebro novato :-) – Methodician

1

También me costó mucho entender los códigos generados por Visual Studio. En lugar de proporcionar una explicación general sobre la expresión lambda, me gustaría poner un contexto utilizando ASP.NET MVC framework.

Supongamos que preparamos una clase de modelo (por ejemplo, Destino) con 2 atributos: Ciudad y Código de provincia.

public class Destination 
{ 
    public string City { get; set; } 
    public string ProvinceCode { get; set; } 
} 

Después de generar el controlador y la opinión, deberíamos obtener los códigos generados por Visual Studio como se ha mencionado. Sin embargo, los códigos generados son algo difícil de entender, especialmente para las filas de datos

@Html.DisplayFor(modelItem => item.City) 

acabo supongo que el equipo MVC debe pensar que clase de ayuda HTML debe ser utilizado constantemente en el archivo cshtml. Por lo tanto, trataron de usar trucos para pasar el compilador de C#. En este caso, modelItem ni siquiera se usa como un parámetro de entrada de esta expresión lambda. No podemos usar() ya que el tipo es NO correcto. Por eso, si reemplazamos modelo o cualquier objeto modelo, la expresión lambda funciona.

Para ser honesto, me gustaría volver a escribir los códigos generados en una forma más legible. En lugar de utilizar el código HTML clase de ayuda , podemos simplemente hacer que la salida correcta de la siguiente manera:

@foreach (var item in Model) { 
<tr>   
    <td> 
     @* Code Generated by Visual Studio. modelItem is a dummy param *@ 
     @Html.DisplayFor(modelItem => item.City) 
    </td> 
    <td> 
     @* A better way - simply get rid of Html helper class *@ 
     @item.ProvinceCode 
    </td> 
</tr> 
} 
Cuestiones relacionadas