我想了解@ Html.DisplayFor中的lambda表达式(modelItem => item.FirstName)

时间:2012-04-10 23:41:22

标签: c# asp.net-mvc razor lambda html-helper

我在C#和MVC上相当新,并且在某些场合使用过lambda,例如匿名方法和LINQ。

通常我看到lambda表达式看起来像这样:

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

我理解lambda =“转到”。我从未见过没有使用左参数的lambda表达式。

我不知道如何翻译这个lambda表达式

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

任何人都可以为我揭开这一点吗?不应该这样

(modelItem => modelItem.FirstName)?

我是从微软的Introduction to ASP.NET MVC tutorial得到的。

4 个答案:

答案 0 :(得分:96)

lambda表达式是一种编写匿名函数的方法,即没有名称的函数。 “箭头”左侧的内容是函数参数,右侧的函数体是函数体。因此,(x => x.Name)在逻辑上转换为类似string Function(Data x) { return x.Name }的类型stringData明显会发生变化并从上下文中派生出来。

缺少左侧参数会转换为不带参数的函数,因此(() => someVariable)逻辑上转换为:string Function() { return someVariable; }

此时您可能会开始疑惑,someVariable来自何处,它不是函数参数,并且未在函数中定义。你是对的,像这样的函数永远不会编译。然而,像这样的lambda函数非常精细,因为它允许提取外部作用域变量并以这种方式使用。 (在内部创建一个包装类,其中lambda表达式中使用的变量成为字段。)

现在让我们看看model => item.FirstName的含义。从逻辑上讲,它会转换为string Function(Model model) { return item.FirstName; }。基本上这是一个带参数的函数,但不使用此参数。

现在,最后一点信息。虽然lambda表达式最终代表函数,但有时创建它们的目的并不是为了实际执行(尽管它们可以)。 lambda表达式可以表达式树的形式表示。这意味着它可以解析。而不是执行它。

在这种特殊情况下,MVC引擎不会运行 lambda表达式所代表的函数。相反,表达式是解析,以便MVC引擎知道要为此特定行发出的html。如果您的数据项不是直接来自模型对象,则lambda表达式的左侧部分无关紧要。

答案 1 :(得分:6)

我认为这是关于foreach循环的。例如:

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

var item,因为序列中的每个项都是匿名类型。 model => item.firstName表示(input parameter) => expression。您不能使用输入参数,因为我们将当前“项目”存储在item

答案 2 :(得分:4)

它使用无参数lambada。见question

基本上DisplayFor不使用lambda函数参数模型(它可以是我所说的任何使用_或())并且只是使用for循环中的lambda函数来对它使用displayfor。 DisplayFor需要一个lambda函数。

答案 3 :(得分:1)

我也很难理解Visual Studio生成的代码。我想提供一个使用ASP.NET MVC框架的上下文,而不是提供有关lambda表达式的一般解释。

假设我们准备了一个具有2个属性的Model类(例如Destination):City和ProvinceCode。

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

生成Controller和View后,我们应该按照提到的Visual Studio获取生成的代码。然而,生成的代码有点难以理解,特别是对于数据行

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

我只是猜测 MVC团队应该认为应该在cshtml文件中始终使用Html帮助程序类。因此,他们试图使用技巧来传递C#编译器。在这种情况下,modelItem甚至不用作此lambda表达式的输入参数。我们不能使用(),因为类型 NOT 正确。这就是为什么,如果我们替换模型或任何模型对象,lambda表达式就可以工作。

老实说,我想以更易读的形式重写生成的代码。我们可以简单地渲染正确的输出,而不是使用 Html 辅助类,如下所示:

@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>
}