我在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得到的。
答案 0 :(得分:96)
lambda表达式是一种编写匿名函数的方法,即没有名称的函数。 “箭头”左侧的内容是函数参数,右侧的函数体是函数体。因此,(x => x.Name)
在逻辑上转换为类似string Function(Data x) { return x.Name }
的类型string
和Data
明显会发生变化并从上下文中派生出来。
缺少左侧参数会转换为不带参数的函数,因此(() => 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>
}