C# .NET Framework 中的 lambdas 和委托之间有什么区别?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/73227/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is the difference between lambdas and delegates in the .NET Framework?
提问by ScottKoon
I get asked this question a lot and I thought I'd solicit some input on how to best describe the difference.
我经常被问到这个问题,我想我会就如何最好地描述差异征求一些意见。
采纳答案by Chris Ammerman
They are actually two very different things. "Delegate" is actually the name for a variable that holds a reference to a method or a lambda, and a lambda is a method without a permanent name.
它们实际上是两个非常不同的东西。“委托”实际上是保存对方法或 lambda 的引用的变量的名称,而 lambda 是没有永久名称的方法。
Lambdas are very much like other methods, except for a couple subtle differences.
Lambda 与其他方法非常相似,除了一些细微的差异。
- A normal method is defined in a "statement"and tied to a permanent name, whereas a lambda is defined "on the fly" in an "expression"and has no permanent name.
- Some lambdas can be used with .NET expression trees, whereas methods cannot.
- 普通方法在“语句”中定义并与永久名称相关联,而 lambda 则在“表达式”中“动态”定义并且没有永久名称。
- 某些 lambda 表达式可以与 .NET 表达式树一起使用,而方法则不能。
A delegate is defined like this:
一个委托的定义如下:
delegate Int32 BinaryIntOp(Int32 x, Int32 y);
A variable of type BinaryIntOp can have either a method or a labmda assigned to it, as long as the signature is the same: two Int32 arguments, and an Int32 return.
BinaryIntOp 类型的变量可以分配一个方法或一个 labmda,只要签名相同:两个 Int32 参数和一个 Int32 返回值。
A lambda might be defined like this:
一个 lambda 可能是这样定义的:
BinaryIntOp sumOfSquares = (a, b) => a*a + b*b;
Another thing to note is that although the generic Func and Action types are often considered "lambda types", they are just like any other delegates. The nice thing about them is that they essentially define a name for any type of delegate you might need (up to 4 parameters, though you can certainly add more of your own). So if you are using a wide variety of delegate types, but none more than once, you can avoid cluttering your code with delegate declarations by using Func and Action.
另一件要注意的事情是,虽然泛型 Func 和 Action 类型通常被认为是“lambda 类型”,但它们就像任何其他委托一样。它们的好处在于它们本质上为您可能需要的任何类型的委托定义了一个名称(最多 4 个参数,但您当然可以添加更多自己的参数)。因此,如果您使用多种委托类型,但仅使用一次,则可以通过使用 Func 和 Action 来避免使用委托声明使代码混乱。
Here is an illustration of how Func and Action are "not just for lambdas":
下面是 Func 和 Action 如何“不仅仅适用于 lambdas”的说明:
Int32 DiffOfSquares(Int32 x, Int32 y)
{
return x*x - y*y;
}
Func<Int32, Int32, Int32> funcPtr = DiffOfSquares;
Another useful thing to know is that delegate types (not methods themselves) with the same signature but different names will not be implicitly casted to each other. This includes the Func and Action delegates. However if the signature is identical, you can explicitly cast between them.
要知道的另一件有用的事情是具有相同签名但不同名称的委托类型(而不是方法本身)不会相互隐式转换。这包括 Func 和 Action 委托。但是,如果签名相同,则可以在它们之间进行显式转换。
Going the extra mile.... In C# functions are flexible, with the use of lambdas and delegates. But C# does not have "first-class functions". You can use a function's name assigned to a delegate variable to essentially create an object representing that function. But it's really a compiler trick. If you start a statement by writing the function name followed by a dot (i.e. try to do member access on the function itself) you'll find there are no members there to reference. Not even the ones from Object. This prevents the programmer from doing useful (and potentially dangerous of course) things such as adding extension methods that can be called on any function. The best you can do is extend the Delegate class itself, which is surely also useful, but not quite as much.
加倍努力.... 在 C# 中,函数是灵活的,使用 lambdas 和委托。但是 C# 没有“一流的功能”。您可以使用分配给委托变量的函数名称来创建代表该函数的对象。但这确实是一个编译器技巧。如果您通过编写函数名后跟一个点来开始一个语句(即尝试对函数本身进行成员访问),您会发现那里没有可引用的成员。甚至不是来自 Object. 这可以防止程序员做有用的(当然也有潜在危险)的事情,比如添加可以在任何函数上调用的扩展方法。您能做的最好的事情是扩展 Delegate 类本身,这当然也很有用,但不是那么有用。
Update: Also see Karg's answerillustrating the difference between anonymous delegates vs. methods & lambdas.
更新:另请参阅Karg 的回答,说明匿名委托与方法和 lambdas 之间的区别。
Update 2: James Hartmakes an important, though very technical, note that lambdas and delegates are not .NET entities (i.e. the CLR has no concept of a delegate or lambda), but rather they are framework and language constructs.
更新 2:James Hart提出了一个重要但技术性很强的注意事项,即 lambda 和委托不是 .NET 实体(即 CLR 没有委托或 lambda 的概念),而是框架和语言结构。
回答by Joel Coehoorn
Well, the really oversimplified version is that a lambda is just shorthand for an anonymous function. A delegate can do a lot more than just anonymous functions: things like events, asynchronous calls, and multiple method chains.
好吧,真正过于简化的版本是 lambda 只是匿名函数的简写。委托可以做的不仅仅是匿名函数:事件、异步调用和多个方法链等。
回答by chessguy
I don't have a ton of experience with this, but the way I would describe it is that a delegate is a wrapper around any function, whereas a lambda expression is itself an anonymous function.
我对此没有丰富的经验,但我要描述的方式是委托是任何函数的包装器,而 lambda 表达式本身是一个匿名函数。
回答by Dan Shield
Delegates are equivalent to function pointers/method pointers/callbacks (take your pick), and lambdas are pretty much simplified anonymous functions. At least that's what I tell people.
委托相当于函数指针/方法指针/回调(随便选),而 lambdas 是非常简化的匿名函数。至少我是这样告诉人们的。
回答by Gilligan
lambdas are simply syntactic sugar on a delegate. The compiler ends up converting lambdas into delegates.
lambda 只是委托上的语法糖。编译器最终将 lambda 转换为委托。
These are the same, I believe:
这些都是一样的,我相信:
Delegate delegate = x => "hi!";
Delegate delegate = delegate(object x) { return "hi";};
回答by Steve Cooper
A delegate is a function signature; something like
委托是一个函数签名;就像是
delegate string MyDelegate(int param1);
The delegate does not implement a body.
委托不实现主体。
The lambda is a function call that matches the signature of the delegate. For the above delegate, you might use any of;
lambda 是一个与委托签名匹配的函数调用。对于上述委托,您可以使用任何一个;
(int i) => i.ToString();
(int i) => "ignored i";
(int i) => "Step " + i.ToString() + " of 10";
The Delegate
type is badly named, though; creating an object of type Delegate
actually creates a variable which can hold functions -- be they lambdas, static methods, or class methods.
但是,该Delegate
类型的名称很糟糕;创建一个类型的对象Delegate
实际上创建了一个可以保存函数的变量——无论是 lambdas、静态方法还是类方法。
回答by Curt Hagenlocher
A delegate is always just basically a function pointer. A lambda can turn into a delegate, but it can also turn into a LINQ expression tree. For instance,
委托基本上只是一个函数指针。一个 lambda 可以变成一个委托,但它也可以变成一个 LINQ 表达式树。例如,
Func<int, int> f = x => x + 1;
Expression<Func<int, int>> exprTree = x => x + 1;
The first line produces a delegate, while the second produces an expression tree.
第一行产生一个委托,而第二行产生一个表达式树。
回答by Steve g
Delegates are really just structural typing for functions. You could do the same thing with nominal typing and implementing an anonymous class that implements an interface or abstract class, but that ends up being a lot of code when only one function is needed.
委托实际上只是函数的结构类型。您可以使用名义类型和实现一个实现接口或抽象类的匿名类来做同样的事情,但是当只需要一个函数时,这最终会成为大量代码。
Lambda comes from the idea of lambda calculus of Alonzo Church in the 1930s. It is an anonymous way of creating functions. They become especially useful for composing functions
Lambda 来自 1930 年代 Alonzo Church 的 lambda 演算思想。它是一种创建函数的匿名方式。它们对于组合函数变得特别有用
So while some might say lambda is syntactic sugar for delegates, I would says delegates are a bridge for easing people into lambdas in c#.
因此,虽然有些人可能会说 lambda 是代表的语法糖,但我会说代表是让人们轻松使用 c# 中的 lambda 的桥梁。
回答by Michael Meadows
Lambdas are simplified versions of delegates. They have some of the the properties of a closurelike anonymous delegates, but also allow you to use implied typing. A lambda like this:
Lambda 是委托的简化版本。它们具有闭包的一些属性,如匿名委托,但也允许您使用隐式类型。像这样的 lambda:
something.Sort((x, y) => return x.CompareTo(y));
is a lot more concise than what you can do with a delegate:
比使用委托所做的要简洁得多:
something.Sort(sortMethod);
...
private int sortMethod(SomeType one, SomeType two)
{
one.CompareTo(two)
}
回答by Karg
One difference is that an anonymous delegate can omit parameters while a lambda must match the exact signature. Given:
一个区别是匿名委托可以省略参数,而 lambda 必须匹配精确的签名。鉴于:
public delegate string TestDelegate(int i);
public void Test(TestDelegate d)
{}
you can call it in the following four ways (note that the second line has an anonymous delegate that does not have any parameters):
您可以通过以下四种方式调用它(注意第二行有一个不带任何参数的匿名委托):
Test(delegate(int i) { return String.Empty; });
Test(delegate { return String.Empty; });
Test(i => String.Empty);
Test(D);
private string D(int i)
{
return String.Empty;
}
You cannot pass in a lambda expression that has no parameters or a method that has no parameters. These are not allowed:
您不能传入没有参数的 lambda 表达式或没有参数的方法。这些是不允许的:
Test(() => String.Empty); //Not allowed, lambda must match signature
Test(D2); //Not allowed, method must match signature
private string D2()
{
return String.Empty;
}