好的,为了清楚起见,我将再次写出这两个(并稍微修改方法以使其更短)
public static Func<HtmlHelper, PropertyViewModel, string> RenderDelegate = (a, b) =>
{
return a.RenderPartial(b);
};
public static string RenderMethod(HtmlHelper a, PropertyViewModel b)
{
return a.RenderPartial(b);
}
首先请注意RenderDelegate 是(如 S. DePouw 所写),只是使用 lambda 语法编写以下内容的一种奇特方式:
public static Func<HtmlHelper, PropertyViewModel, string> RenderDelegate =
delegate(HtmlHelper a, PropertyViewModel b)
{
return a.RenderPartial(b);
};
RenderMethod 和RenderDelegate 之间的区别在于RenderMethod 是一个方法,而RenderDelegate 是一个委托,或者更具体地说是一个委托类型的字段。这意味着可以将 RenderDelegate 分配给。
什么是委托?
委托是一种类型。来自MSDN documentation:
委托是一种定义方法签名的类型,可以与任何具有兼容签名的方法相关联。
基本上,您可以将委托视为方法的引用/指针,但是委托所指向的方法必须与委托所期望的签名相匹配。例如,Func<HtmlHelper, PropertyViewModel, string> 是一个委托,它需要签名为 string MyMethod(HtmlHelper, PropertyViewModel) 的方法,因此我们可以将具有该签名的方法分配给该委托,如下所示:
RenderDelegate = RenderMethod;
请务必注意 Delegate 类型(注意大写 D)和 delegate 关键字(小写 d)之间的区别。在您的示例中,您使用Func<> 通用对象来压缩您的代码,但是它有点模糊了这里真正发生的事情。 Func<HtmlHelper, PropertyViewModel, string> 是继承自 Delegate 的类型,您可以使用 delegate 关键字来删除等价类型:
delegate string MyFunction<HtmlHelper helper, PropertyViewModel string>;
static MyFunction RenderDelegate = RenderMethod;
匿名方法
当我们在第一个示例中分配 RenderDelegate 时,我们没有将 RenderDelegate 设置为现有的命名方法,而是在线声明了一个新方法。这被称为匿名方法并且有效,因为我们能够将代码块(也使用委托关键字声明)作为委托参数传递:
Lambda 函数
回到原来的语法——你的例子是使用 lambda 语法以一种有趣的方式来删除匿名委托。 Lambda 表达式是声明短内联方法的好方法,这些方法在处理列表时可能经常使用,例如,假设我们要按名称对 HtmlHelper 对象列表进行排序。这样做的方法是将比较两个 HtmlHelper 对象的 Delegate 传递给列表的 Sort 方法,然后 sort 方法使用该委托对列表中的元素进行比较和排序:
static int MyComparison(HtmlHelper x, HtmlHelper y)
{
return x.Name.CompareTo(y.Name);
}
static void Main()
{
List<HtmlHelper> myList = GetList();
myList.Sort(MyComparison);
}
为了避免大量的短方法分散在各处,您可以使用匿名方法来内联删除排序方法。真正有用的是,内联方法可以访问在包含范围内声明的变量:
int myInt = 12;
List<HtmlHelper> myList = GetList();
myList.Sort(
delegate (HtmlHelper x, HtmlHelper y)
{
return x.Name.CompareTo(y.Name) - myInt;
});
然而,这仍然是相当多的输入,因此 lambda 语法诞生了,现在您可以这样做:
List<HtmlHelper> myList = GetList();
myList.Sort((x, y) => {return x.Name.CompareTo(y.Name)});
然而,以这种方式声明“正常”方法对我来说似乎完全没有意义(并且让我的眼睛流血)
代表非常非常有用,并且(除其他外)是 .Net 事件系统的基石。更多阅读以澄清一些事情: