我经常被问到这个问题,我想我应该就如何最好地描述不同之处征求一些意见.

推荐答案

它们实际上是两种截然不同的东西."Delegate"实际上是一个变量的名称,该变量包含对方法或lambda的引用,lambda是一个没有永久名称的方法.

lambda与其他方法非常相似,只是有一些细微的区别.

  1. 普通方法在"statement"中定义并绑定到永久名称,而lambda在"expression"中定义为"动态",没有永久名称.
  2. 一些lambda可以用于.NET表达式树,而方法不能.

委托的定义如下:

delegate Int32 BinaryIntOp(Int32 x, Int32 y);

BinaryIntOp类型的变量可以指定方法或labmda,只要签名相同:两个Int32参数和一个Int32返回.

lambda可能定义如下:

BinaryIntOp sumOfSquares = (a, b) => a*a + b*b;

另一件需要注意的事情是,尽管泛型Func和Action类型通常被认为是"lambda类型",但它们与任何其他委托一样.它们的优点在于,它们本质上为您可能需要的任何类型的委托定义了一个名称(最多4个参数,不过您当然可以添加更多自己的参数).因此,如果要使用多种委托类型,但只使用一次,那么可以通过使用Func和Action避免代码中委托声明的混乱.

以下是Func和Action"不仅仅适用于lambdas"的示例:

Int32 DiffOfSquares(Int32 x, Int32 y)
{
  return x*x - y*y;
}

Func<Int32, Int32, Int32> funcPtr = DiffOfSquares;

需要知道的另一件有用的事情是,具有相同签名但名称不同的委托类型(不是方法本身)不会被隐式转换为彼此.这包括Func和Action代理.但是,如果签名相同,则可以在它们之间显式转换.

多走一英里....在C语言中,函数是灵活的,可以使用lambda和委托.但C#没有"一流的功能".可以使用分配给委托变量的函数名来创建表示该函数的对象.但这真的是一个编译技巧.如果你在开始一条语句时先写函数名,然后写一个点(即try 对函数本身进行成员访问),你会发现没有成员可供引用.甚至不是来自Object的.这会阻止程序员做一些有用(当然也有潜在危险)的事情,比如添加可以在任何函数上调用的扩展方法.您所能做的最好的事情就是扩展委托类本身,这当然也很有用,但没有那么多.

更新:另请参见Karg's answer,说明匿名代表与方法之间的区别;兰巴斯.

更新2:James Hart是一个重要的,尽管非常技术性的问题,但请注意,lambdas和代表们并非如此.NET实体(即CLR没有委托或lambda的概念),但它们是框架和语言构造.

.net相关问答推荐

从窗体中移除另一个控件中引用的控件时获取设计时通知

如何手动注入依赖注入

如何使用 Moq 为不同的参数设置两次方法

.NET 中是否有一种简单的方法来获得数字的st、nd、rd和th结尾?

如何获取 Sql Server 数据库中所有模式的列表

File.ReadAllLines() 和 File.ReadAllText() 有什么区别?

如何在 C# 中直接执行 SQL 查询?

有什么方法可以在不重新编译的情况下覆盖 .NET Windows 服务名称?

什么是 SUT,它来自哪里?

基于多个字符分隔符拆分字符串

我可以在没有两个查询的情况下通过布尔标准将 IEnumerable 一分为二吗?

dotnet 恢复警告 NU1701

.NET 中的对象引用有多大?

Moq - 不可覆盖的成员不能用于设置/验证表达式

Dispatcher.CurrentDispatcher 与 Application.Current.Dispatcher

我应该绑定到 ICollectionView 还是 ObservableCollection

为什么 Roslyn 中有异步状态机类(而不是 struct )?

如果选中,则更改列表框项的 WPF DataTemplate

是 C# 中的 bool 读/写原子

您可以将 Microsoft Entity Framework 与 Oracle 一起使用吗?