net框架中的lambdas和委托之间有什么区别?

时间:2022-05-21 20:40:15

I get asked this question a lot and I thought I'd solicit some input on how to best describe the difference.

我经常被问到这个问题,我想我应该征求一些关于如何最好地描述差异的意见。

17 个解决方案

#1


70  

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.

它们实际上是两个完全不同的东西。“Delegate”实际上是一个变量的名称,它包含对方法或lambda的引用,lambda是一个没有永久名称的方法。

Lambdas are very much like other methods, except for a couple subtle differences.

Lambdas非常类似于其他方法,除了一些细微的差异。

  1. 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.
  2. 普通的方法在“语句”中定义,并绑定到一个永久名称,而lambda在“表达式”中定义为“动态”,并且没有永久名称。
  3. Some lambdas can be used with .NET expression trees, whereas methods cannot.
  4. 有些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和动作委托。但是,如果签名是相同的,则可以显式地在它们之间进行转换。

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和delegate。但是c#没有“一流的功能”。您可以使用分配给委托变量的函数名来创建一个表示该函数的对象。但这确实是一个编译技巧。如果在语句开始时先写入函数名,然后加上一个点(例如,尝试对函数本身进行成员访问),您将发现那里没有要引用的成员。甚至不是来自物体的。这阻止程序员做一些有用的事情(当然也有潜在的危险),比如添加可以在任何函数上调用的扩展方法。您所能做的最好的事情就是扩展委托类本身,这当然也很有用,但并没有那么有用。

Update: Also see Karg's answer illustrating the difference between anonymous delegates vs. methods & lambdas.

更新:请参见Karg的回答,说明匿名委托与方法& lambdas之间的区别。

Update 2: James Hart makes 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指出,尽管非常技术性,但lambdas和delegate不是. net实体(即CLR没有委托或lambda概念),而是框架和语言结构。

#2


23  

The question is a little ambiguous, which explains the wide disparity in answers you're getting.

这个问题有点模棱两可,这就解释了你得到的答案之间的巨大差异。

You actually asked what the difference is between lambdas and delegates in the .NET framework; that might be one of a number of things. Are you asking:

您实际上问过。net框架中的lambdas和委托之间有什么区别;这可能是其中之一。你是问:

  • What is the difference between lambda expressions and anonymous delegates in the C# (or VB.NET) language?

    在c#(或VB.NET)语言中,lambda表达式和匿名委托的区别是什么?

  • What is the difference between System.Linq.Expressions.LambdaExpression objects and System.Delegate objects in .NET 3.5?

    System.Linq.Expressions是什么?LambdaExpression对象和系统。在。net 3.5中委托对象?

  • Or something somewhere between or around those extremes?

    或者介于这两个极端之间?

Some people seem to be trying to give you the answer to the question 'what is the difference between C# Lambda expressions and .NET System.Delegate?', which doesn't make a whole lot of sense.

有些人似乎想给你一个问题的答案:“c# Lambda表达式和。net System.Delegate之间有什么区别?”,这没有多大意义。

The .NET framework does not in itself understand the concepts of anonymous delegates, lambda expressions, or closures - those are all things defined by language specifications. Think about how the C# compiler translates the definition of an anonymous method into a method on a generated class with member variables to hold closure state; to .NET, there's nothing anonymous about the delegate; it's just anonymous to the C# programmer writing it. That's equally true of a lambda expression assigned to a delegate type.

. net框架本身并不理解匿名委托、lambda表达式或闭包的概念——这些都是由语言规范定义的。考虑一下c#编译器如何将匿名方法的定义转换为生成的类上的方法,其中包含保持闭包状态的成员变量;对于。net来说,委托没有什么是匿名的;对于编写它的c#程序员来说,它是匿名的。这对于分配给委托类型的lambda表达式同样成立。

What .NET DOES understand is the idea of a delegate - a type that describes a method signature, instances of which represent either bound calls to specific methods on specific objects, or unbound calls to a particular method on a particular type that can be invoked against any object of that type, where said method adheres to the said signature. Such types all inherit from System.Delegate.

理解的是什么。net的想法代表——这种类型描述一个方法签名,表示要么绑定调用特定方法的实例对具体对象,或取消绑定调用特定方法在一个特定的类型,可以对任何类型的对象,调用方法坚持说签名的地方。这些类型都继承自System.Delegate。

.NET 3.5 also introduces the System.Linq.Expressions namespace, which contains classes for describing code expressions - and which can also therefore represent bound or unbound calls to methods on particular types or objects. LambdaExpression instances can then be compiled into actual delegates (whereby a dynamic method based on the structure of the expression is codegenned, and a delegate pointer to it is returned).

. net 3.5也引入了System.Linq。表达式命名空间,它包含描述代码表达式的类——因此也可以表示对特定类型或对象的方法的绑定或非绑定调用。然后可以将LambdaExpression实例编译为实际的委托(基于表达式结构的动态方法是codegenned,并返回它的委托指针)。

In C# you can produce instances of System.Expressions.Expression types by assigning a lambda expression to a variable of said type, which will produce the appropriate code to construct the expression at runtime.

在c#中,您可以生成System.Expressions的实例。表达式类型通过将lambda表达式分配给所述类型的变量,该变量将生成在运行时构造表达式的适当代码。

Of course, if you were asking what the difference is between lambda expressions and anonymous methods in C#, after all, then all this is pretty much irelevant, and in that case the primary difference is brevity, which leans towards anonymous delegates when you don't care about parameters and don't plan on returning a value, and towards lambdas when you want type inferenced parameters and return types.

当然,如果你问lambda表达式和匿名方法之间的区别是在c#中,毕竟,那么这是几乎irelevant,和在这种情况下,主要的区别是简洁,而倾向于匿名代表当你不在乎参数和不打算返回一个值,并对λ当你想要的类型推断的参数和返回类型。

And lambda expressions support expression generation.

lambda表达式支持表达式生成。

#3


16  

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

#4


12  

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是非常简单的匿名函数。至少我是这么告诉人们的。

#5


3  

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表达式本身就是一个匿名函数。

#6


3  

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.

第一行生成委托,而第二行生成表达式树。

#7


2  

lambdas are simply syntactic sugar on a delegate. The compiler ends up converting lambdas into delegates.

lambda只是委托上的语法糖。编译器最终将lambdas转换为委托。

These are the same, I believe:

我相信它们是一样的:

Delegate delegate = x => "hi!";
Delegate delegate = delegate(object x) { return "hi";};

#8


2  

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.

但是,委托类型命名不正确;创建类型委托的对象实际上创建了一个可以保存函数的变量——可以是lambda、静态方法或类方法。

#9


2  

A delegate is a reference to a method with a particular parameter list and return type. It may or may not include an object.

委托是对具有特定参数列表和返回类型的方法的引用。它可能包含也可能不包含对象。

A lambda-expression is a form of anonymous function.

lambda表达式是匿名函数的一种形式。

#10


2  

It is pretty clear the question was meant to be "what's the difference between lambdas and anonymous delegates?" Out of all the answers here only one person got it right - the main difference is that lambdas can be used to create expression trees as well as delegates.

很明显,问题是“lambdas和匿名代表之间有什么区别?”在所有的答案中,只有一个人是正确的——主要的区别是,lambdas可以用来创建表达式树和委托。

You can read more on MSDN: http://msdn.microsoft.com/en-us/library/bb397687.aspx

你可以在MSDN上阅读更多:http://msdn.microsoft.com/en-us/library/bb397687.aspx

#11


1  

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源于20世纪30年代对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#中轻松阅读lambdas的桥梁。

#12


1  

A delegate is a Queue of function pointers, invoking a delegate may invoke multiple methods. A lambda is essentially an anonymous method declaration which may be interpreted by the compiler differently, depending on what context it is used as.

委托是函数指针的队列,调用委托可以调用多个方法。lambda本质上是一个匿名方法声明,编译器可以根据使用的上下文对其进行不同的解释。

You can get a delegate that points to the lambda expression as a method by casting it into a delegate, or if passing it in as a parameter to a method that expects a specific delegate type the compiler will cast it for you. Using it inside of a LINQ statement, the lambda will be translated by the compiler into an expression tree instead of simply a delegate.

您可以通过将lambda表达式转换为委托来获得指向lambda表达式的委托,或者将其作为参数传递给需要特定委托类型的方法,编译器将为您强制它。在LINQ语句中使用它,编译器将把lambda翻译成表达式树,而不仅仅是委托。

The difference really is that a lambda is a terse way to define a method inside of another expression, while a delegate is an actual object type.

区别在于,lambda是在另一个表达式内部定义方法的简洁方法,而委托是实际的对象类型。

#13


0  

Lambdas are simplified versions of delegates. They have some of the the properties of a closure like anonymous delegates, but also allow you to use implied typing. A lambda like this:

Lambdas是委托的简化版本。它们具有像匿名委托这样的闭包的一些属性,但也允许您使用隐含的类型。一个λ是这样的:

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

#14


0  

Heres an example I put up awhile on my lame blog. Say you wanted to update a label from a worker thread. I've got 4 examples of how to update that label from 1 to 50 using delegates, anon delegates and 2 types of lambdas.

这是我在我的蹩脚博客上写的一个例子。假设您想从一个工作线程更新一个标签。我有4个示例说明如何使用委托、anon委托和两种类型的lambdas将该标签从1更新到50。

 private void button2_Click(object sender, EventArgs e) 
     { 
         BackgroundWorker worker = new BackgroundWorker(); 
         worker.DoWork += new DoWorkEventHandler(worker_DoWork); 
         worker.RunWorkerAsync(); 
     } 

     private delegate void UpdateProgDelegate(int count); 
     private void UpdateText(int count) 
     { 
         if (this.lblTest.InvokeRequired) 
         { 
             UpdateProgDelegate updateCallBack = new UpdateProgDelegate(UpdateText); 
             this.Invoke(updateCallBack, new object[] { count }); 
         } 
         else 
         { 
             lblTest.Text = count.ToString(); 
         } 
     } 

     void worker_DoWork(object sender, DoWorkEventArgs e) 
     {   
         /* Old Skool delegate usage.  See above for delegate and method definitions */ 
         for (int i = 0; i < 50; i++) 
         { 
             UpdateText(i); 
             Thread.Sleep(50); 
         } 

         // Anonymous Method 
         for (int i = 0; i < 50; i++) 
         { 
             lblTest.Invoke((MethodInvoker)(delegate() 
             { 
                 lblTest.Text = i.ToString(); 
             })); 
             Thread.Sleep(50); 
         } 

         /* Lambda using the new Func delegate. This lets us take in an int and 
          * return a string.  The last parameter is the return type. so 
          * So Func<int, string, double> would take in an int and a string 
          * and return a double.  count is our int parameter.*/ 
         Func<int, string> UpdateProgress = (count) => lblTest.Text = count.ToString(); 
         for (int i = 0; i < 50; i++) 
         { 
             lblTest.Invoke(UpdateProgress, i); 
             Thread.Sleep(50); 
         } 

         /* Finally we have a totally inline Lambda using the Action delegate 
          * Action is more or less the same as Func but it returns void. We could 
          * use it with parameters if we wanted to like this: 
          * Action<string> UpdateProgress = (count) => lblT…*/ 
         for (int i = 0; i < 50; i++) 
         { 
             lblTest.Invoke((Action)(() => lblTest.Text = i.ToString())); 
             Thread.Sleep(50); 
         } 
     }

#15


0  

I assume that your question concerns c# and not .NET, because of the ambiguity of your question, as .NET does not get alone - that is, without c# - comprehension of delegates and lambda expressions.

我假设您的问题是关于c#而不是。net的,因为您的问题是不明确的,因为。net并不是单独的——也就是说,没有c# -理解委托和lambda表达式。

A (normal, in opposition to so called generic delegates, cf later) delegate should be seen as a kind of c++ typedef of a function pointer type, for instance in c++ :

A (normal,与所谓的泛型委托相反,cf later)委托应该被视为一种函数指针类型的c++类型定义,例如在c++中:

R (*thefunctionpointer) ( T ) ;

typedef's the type thefunctionpointer which is the type of pointers to a function taking an object of type T and returning an object of type R. You would use it like this :

typedef类型是thefunctionpointer类型它是指向函数的指针它接收类型为T的对象并返回类型为r的对象

thefunctionpointer = &thefunction ;
R r = (*thefunctionpointer) ( t ) ; // where t is of type T

where thefunction would be a function taking a T and returning an R.

函数是一个取T,返回R的函数。

In c# you would go for

在c#中,你会选择

delegate R thedelegate( T t ) ; // and yes, here the identifier t is needed

and you would use it like this :

你可以这样使用它:

thedelegate thedel = thefunction ;
R r = thedel ( t ) ; // where t is of type T

where thefunction would be a function taking a T and returning an R. This is for delegates, so called normal delegates.

函数是一个取T并返回r的函数,这是代表,也就是所谓的普通代表。

Now, you also have generic delegates in c#, which are delegates that are generic, i.e. that are "templated" so to speak, using thereby a c++ expression. They are defined like this :

现在,您还有c#中的泛型委托,它们是泛型的委托,即所谓的“模板化”委托,使用c++表达式。它们的定义如下:

public delegate TResult Func<in T, out TResult>(T arg);

And you can used them like this :

你可以这样使用它们:

Func<double, double> thefunctor = thefunction2; // call it a functor because it is
                                                // really as a functor that you should
                                                // "see" it
double y = thefunctor(2.0);

where thefunction2 is a function taking as argument and returning a double.

函数2是一个函数,作为参数并返回一个double。

Now imagine that instead of thefunction2 I would like to use a "function" that is nowhere defined for now, by a statement, and that I will never use later. Then c# allows us to use the expression of this function. By expression I mean the "mathematical" (or functional, to stick to programs) expression of it, for instance : to a double x I will associate the double x*x. In maths you write this using the "\mapsto" latex symbol. In c# the functional notation has been borrowed : =>. For instance :

现在,假设我想使用一个“函数”,而不是thefunction2,这个“函数”现在还没有通过语句定义,以后我将不会使用它。然后c#允许我们使用这个函数的表达式。我说的表达式是指它的“数学”(或函数)表达式,例如:对于双x,我将把双x*x联系起来。在数学中,你用“\mapsto”乳胶符号来写这个。在c#中,函数符号被借用:=>。例如:

Func<double, double> thefunctor = ( (double x) => x * x ); // outer brackets are not
                                                           // mandatory

(double x) => x * x is an expression. It is not a type, whereas delegates (generic or not) are.

(double x) => x * x是一个表达式。它不是类型,而委托(通用的或非通用的)是。

Morality ? At end, what is a delegate (resp. generic delegate), if not a function pointer type (resp. wrapped+smart+generic function pointer type), huh ? Something else ! See this and that.

道德?最后,什么是委托(resp)。泛型委托),如果不是函数指针类型(resp)。包装+智能+通用函数指针类型),嗯?别的东西!看到这个,。

#16


0  

Some basic here. "Delegate" is actually the name for a variable that holds a reference to a method or a lambda

一些基本的。“Delegate”实际上是一个变量的名称,它包含对方法或lambda的引用

This is a anonymous method - (string testString) => { Console.WriteLine(testString); };

这是一个匿名方法—(string testString) => {Console.WriteLine(testString);};

As anonymous method do not have any name we need a delegate in which we can assign both of these method or expression. For Ex.

由于匿名方法没有任何名称,所以我们需要一个委托,在这个委托中我们可以同时分配这两个方法或表达式。前女友。

delegate void PrintTestString(string testString); // declare a delegate

委托无效PrintTestString(string testString);/ /声明一个委托

PrintTestString print = (string testString) => { Console.WriteLine(testString); }; print();

PrintTestString print = (string testString) => {Console.WriteLine(testString);};print();


Same with the lambda expression. Usually we need delegate to use them

和表达式一样。通常我们需要委托来使用它们

s => s.Age > someValue && s.Age < someValue // will return true/false

= >年代。年龄>岁以上。年龄< someValue //将返回true/false

We can use a func delegate to use this expression.

我们可以使用func委托来使用这个表达式。

Func< Student,bool> checkStudentAge = s => s.Age > someValue && s.Age < someValue ;

Func< Student,bool> checkStudentAge = s => . s。年龄>岁以上。年龄< someValue;

bool result = checkStudentAge ( Student Object);

bool结果= checkStudentAge(学生对象);

#17


-1  

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只是对匿名函数的一种简化。委托可以做的不仅仅是匿名函数:事件、异步调用和多个方法链。

#1


70  

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.

它们实际上是两个完全不同的东西。“Delegate”实际上是一个变量的名称,它包含对方法或lambda的引用,lambda是一个没有永久名称的方法。

Lambdas are very much like other methods, except for a couple subtle differences.

Lambdas非常类似于其他方法,除了一些细微的差异。

  1. 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.
  2. 普通的方法在“语句”中定义,并绑定到一个永久名称,而lambda在“表达式”中定义为“动态”,并且没有永久名称。
  3. Some lambdas can be used with .NET expression trees, whereas methods cannot.
  4. 有些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和动作委托。但是,如果签名是相同的,则可以显式地在它们之间进行转换。

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和delegate。但是c#没有“一流的功能”。您可以使用分配给委托变量的函数名来创建一个表示该函数的对象。但这确实是一个编译技巧。如果在语句开始时先写入函数名,然后加上一个点(例如,尝试对函数本身进行成员访问),您将发现那里没有要引用的成员。甚至不是来自物体的。这阻止程序员做一些有用的事情(当然也有潜在的危险),比如添加可以在任何函数上调用的扩展方法。您所能做的最好的事情就是扩展委托类本身,这当然也很有用,但并没有那么有用。

Update: Also see Karg's answer illustrating the difference between anonymous delegates vs. methods & lambdas.

更新:请参见Karg的回答,说明匿名委托与方法& lambdas之间的区别。

Update 2: James Hart makes 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指出,尽管非常技术性,但lambdas和delegate不是. net实体(即CLR没有委托或lambda概念),而是框架和语言结构。

#2


23  

The question is a little ambiguous, which explains the wide disparity in answers you're getting.

这个问题有点模棱两可,这就解释了你得到的答案之间的巨大差异。

You actually asked what the difference is between lambdas and delegates in the .NET framework; that might be one of a number of things. Are you asking:

您实际上问过。net框架中的lambdas和委托之间有什么区别;这可能是其中之一。你是问:

  • What is the difference between lambda expressions and anonymous delegates in the C# (or VB.NET) language?

    在c#(或VB.NET)语言中,lambda表达式和匿名委托的区别是什么?

  • What is the difference between System.Linq.Expressions.LambdaExpression objects and System.Delegate objects in .NET 3.5?

    System.Linq.Expressions是什么?LambdaExpression对象和系统。在。net 3.5中委托对象?

  • Or something somewhere between or around those extremes?

    或者介于这两个极端之间?

Some people seem to be trying to give you the answer to the question 'what is the difference between C# Lambda expressions and .NET System.Delegate?', which doesn't make a whole lot of sense.

有些人似乎想给你一个问题的答案:“c# Lambda表达式和。net System.Delegate之间有什么区别?”,这没有多大意义。

The .NET framework does not in itself understand the concepts of anonymous delegates, lambda expressions, or closures - those are all things defined by language specifications. Think about how the C# compiler translates the definition of an anonymous method into a method on a generated class with member variables to hold closure state; to .NET, there's nothing anonymous about the delegate; it's just anonymous to the C# programmer writing it. That's equally true of a lambda expression assigned to a delegate type.

. net框架本身并不理解匿名委托、lambda表达式或闭包的概念——这些都是由语言规范定义的。考虑一下c#编译器如何将匿名方法的定义转换为生成的类上的方法,其中包含保持闭包状态的成员变量;对于。net来说,委托没有什么是匿名的;对于编写它的c#程序员来说,它是匿名的。这对于分配给委托类型的lambda表达式同样成立。

What .NET DOES understand is the idea of a delegate - a type that describes a method signature, instances of which represent either bound calls to specific methods on specific objects, or unbound calls to a particular method on a particular type that can be invoked against any object of that type, where said method adheres to the said signature. Such types all inherit from System.Delegate.

理解的是什么。net的想法代表——这种类型描述一个方法签名,表示要么绑定调用特定方法的实例对具体对象,或取消绑定调用特定方法在一个特定的类型,可以对任何类型的对象,调用方法坚持说签名的地方。这些类型都继承自System.Delegate。

.NET 3.5 also introduces the System.Linq.Expressions namespace, which contains classes for describing code expressions - and which can also therefore represent bound or unbound calls to methods on particular types or objects. LambdaExpression instances can then be compiled into actual delegates (whereby a dynamic method based on the structure of the expression is codegenned, and a delegate pointer to it is returned).

. net 3.5也引入了System.Linq。表达式命名空间,它包含描述代码表达式的类——因此也可以表示对特定类型或对象的方法的绑定或非绑定调用。然后可以将LambdaExpression实例编译为实际的委托(基于表达式结构的动态方法是codegenned,并返回它的委托指针)。

In C# you can produce instances of System.Expressions.Expression types by assigning a lambda expression to a variable of said type, which will produce the appropriate code to construct the expression at runtime.

在c#中,您可以生成System.Expressions的实例。表达式类型通过将lambda表达式分配给所述类型的变量,该变量将生成在运行时构造表达式的适当代码。

Of course, if you were asking what the difference is between lambda expressions and anonymous methods in C#, after all, then all this is pretty much irelevant, and in that case the primary difference is brevity, which leans towards anonymous delegates when you don't care about parameters and don't plan on returning a value, and towards lambdas when you want type inferenced parameters and return types.

当然,如果你问lambda表达式和匿名方法之间的区别是在c#中,毕竟,那么这是几乎irelevant,和在这种情况下,主要的区别是简洁,而倾向于匿名代表当你不在乎参数和不打算返回一个值,并对λ当你想要的类型推断的参数和返回类型。

And lambda expressions support expression generation.

lambda表达式支持表达式生成。

#3


16  

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

#4


12  

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是非常简单的匿名函数。至少我是这么告诉人们的。

#5


3  

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表达式本身就是一个匿名函数。

#6


3  

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.

第一行生成委托,而第二行生成表达式树。

#7


2  

lambdas are simply syntactic sugar on a delegate. The compiler ends up converting lambdas into delegates.

lambda只是委托上的语法糖。编译器最终将lambdas转换为委托。

These are the same, I believe:

我相信它们是一样的:

Delegate delegate = x => "hi!";
Delegate delegate = delegate(object x) { return "hi";};

#8


2  

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.

但是,委托类型命名不正确;创建类型委托的对象实际上创建了一个可以保存函数的变量——可以是lambda、静态方法或类方法。

#9


2  

A delegate is a reference to a method with a particular parameter list and return type. It may or may not include an object.

委托是对具有特定参数列表和返回类型的方法的引用。它可能包含也可能不包含对象。

A lambda-expression is a form of anonymous function.

lambda表达式是匿名函数的一种形式。

#10


2  

It is pretty clear the question was meant to be "what's the difference between lambdas and anonymous delegates?" Out of all the answers here only one person got it right - the main difference is that lambdas can be used to create expression trees as well as delegates.

很明显,问题是“lambdas和匿名代表之间有什么区别?”在所有的答案中,只有一个人是正确的——主要的区别是,lambdas可以用来创建表达式树和委托。

You can read more on MSDN: http://msdn.microsoft.com/en-us/library/bb397687.aspx

你可以在MSDN上阅读更多:http://msdn.microsoft.com/en-us/library/bb397687.aspx

#11


1  

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源于20世纪30年代对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#中轻松阅读lambdas的桥梁。

#12


1  

A delegate is a Queue of function pointers, invoking a delegate may invoke multiple methods. A lambda is essentially an anonymous method declaration which may be interpreted by the compiler differently, depending on what context it is used as.

委托是函数指针的队列,调用委托可以调用多个方法。lambda本质上是一个匿名方法声明,编译器可以根据使用的上下文对其进行不同的解释。

You can get a delegate that points to the lambda expression as a method by casting it into a delegate, or if passing it in as a parameter to a method that expects a specific delegate type the compiler will cast it for you. Using it inside of a LINQ statement, the lambda will be translated by the compiler into an expression tree instead of simply a delegate.

您可以通过将lambda表达式转换为委托来获得指向lambda表达式的委托,或者将其作为参数传递给需要特定委托类型的方法,编译器将为您强制它。在LINQ语句中使用它,编译器将把lambda翻译成表达式树,而不仅仅是委托。

The difference really is that a lambda is a terse way to define a method inside of another expression, while a delegate is an actual object type.

区别在于,lambda是在另一个表达式内部定义方法的简洁方法,而委托是实际的对象类型。

#13


0  

Lambdas are simplified versions of delegates. They have some of the the properties of a closure like anonymous delegates, but also allow you to use implied typing. A lambda like this:

Lambdas是委托的简化版本。它们具有像匿名委托这样的闭包的一些属性,但也允许您使用隐含的类型。一个λ是这样的:

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

#14


0  

Heres an example I put up awhile on my lame blog. Say you wanted to update a label from a worker thread. I've got 4 examples of how to update that label from 1 to 50 using delegates, anon delegates and 2 types of lambdas.

这是我在我的蹩脚博客上写的一个例子。假设您想从一个工作线程更新一个标签。我有4个示例说明如何使用委托、anon委托和两种类型的lambdas将该标签从1更新到50。

 private void button2_Click(object sender, EventArgs e) 
     { 
         BackgroundWorker worker = new BackgroundWorker(); 
         worker.DoWork += new DoWorkEventHandler(worker_DoWork); 
         worker.RunWorkerAsync(); 
     } 

     private delegate void UpdateProgDelegate(int count); 
     private void UpdateText(int count) 
     { 
         if (this.lblTest.InvokeRequired) 
         { 
             UpdateProgDelegate updateCallBack = new UpdateProgDelegate(UpdateText); 
             this.Invoke(updateCallBack, new object[] { count }); 
         } 
         else 
         { 
             lblTest.Text = count.ToString(); 
         } 
     } 

     void worker_DoWork(object sender, DoWorkEventArgs e) 
     {   
         /* Old Skool delegate usage.  See above for delegate and method definitions */ 
         for (int i = 0; i < 50; i++) 
         { 
             UpdateText(i); 
             Thread.Sleep(50); 
         } 

         // Anonymous Method 
         for (int i = 0; i < 50; i++) 
         { 
             lblTest.Invoke((MethodInvoker)(delegate() 
             { 
                 lblTest.Text = i.ToString(); 
             })); 
             Thread.Sleep(50); 
         } 

         /* Lambda using the new Func delegate. This lets us take in an int and 
          * return a string.  The last parameter is the return type. so 
          * So Func<int, string, double> would take in an int and a string 
          * and return a double.  count is our int parameter.*/ 
         Func<int, string> UpdateProgress = (count) => lblTest.Text = count.ToString(); 
         for (int i = 0; i < 50; i++) 
         { 
             lblTest.Invoke(UpdateProgress, i); 
             Thread.Sleep(50); 
         } 

         /* Finally we have a totally inline Lambda using the Action delegate 
          * Action is more or less the same as Func but it returns void. We could 
          * use it with parameters if we wanted to like this: 
          * Action<string> UpdateProgress = (count) => lblT…*/ 
         for (int i = 0; i < 50; i++) 
         { 
             lblTest.Invoke((Action)(() => lblTest.Text = i.ToString())); 
             Thread.Sleep(50); 
         } 
     }

#15


0  

I assume that your question concerns c# and not .NET, because of the ambiguity of your question, as .NET does not get alone - that is, without c# - comprehension of delegates and lambda expressions.

我假设您的问题是关于c#而不是。net的,因为您的问题是不明确的,因为。net并不是单独的——也就是说,没有c# -理解委托和lambda表达式。

A (normal, in opposition to so called generic delegates, cf later) delegate should be seen as a kind of c++ typedef of a function pointer type, for instance in c++ :

A (normal,与所谓的泛型委托相反,cf later)委托应该被视为一种函数指针类型的c++类型定义,例如在c++中:

R (*thefunctionpointer) ( T ) ;

typedef's the type thefunctionpointer which is the type of pointers to a function taking an object of type T and returning an object of type R. You would use it like this :

typedef类型是thefunctionpointer类型它是指向函数的指针它接收类型为T的对象并返回类型为r的对象

thefunctionpointer = &thefunction ;
R r = (*thefunctionpointer) ( t ) ; // where t is of type T

where thefunction would be a function taking a T and returning an R.

函数是一个取T,返回R的函数。

In c# you would go for

在c#中,你会选择

delegate R thedelegate( T t ) ; // and yes, here the identifier t is needed

and you would use it like this :

你可以这样使用它:

thedelegate thedel = thefunction ;
R r = thedel ( t ) ; // where t is of type T

where thefunction would be a function taking a T and returning an R. This is for delegates, so called normal delegates.

函数是一个取T并返回r的函数,这是代表,也就是所谓的普通代表。

Now, you also have generic delegates in c#, which are delegates that are generic, i.e. that are "templated" so to speak, using thereby a c++ expression. They are defined like this :

现在,您还有c#中的泛型委托,它们是泛型的委托,即所谓的“模板化”委托,使用c++表达式。它们的定义如下:

public delegate TResult Func<in T, out TResult>(T arg);

And you can used them like this :

你可以这样使用它们:

Func<double, double> thefunctor = thefunction2; // call it a functor because it is
                                                // really as a functor that you should
                                                // "see" it
double y = thefunctor(2.0);

where thefunction2 is a function taking as argument and returning a double.

函数2是一个函数,作为参数并返回一个double。

Now imagine that instead of thefunction2 I would like to use a "function" that is nowhere defined for now, by a statement, and that I will never use later. Then c# allows us to use the expression of this function. By expression I mean the "mathematical" (or functional, to stick to programs) expression of it, for instance : to a double x I will associate the double x*x. In maths you write this using the "\mapsto" latex symbol. In c# the functional notation has been borrowed : =>. For instance :

现在,假设我想使用一个“函数”,而不是thefunction2,这个“函数”现在还没有通过语句定义,以后我将不会使用它。然后c#允许我们使用这个函数的表达式。我说的表达式是指它的“数学”(或函数)表达式,例如:对于双x,我将把双x*x联系起来。在数学中,你用“\mapsto”乳胶符号来写这个。在c#中,函数符号被借用:=>。例如:

Func<double, double> thefunctor = ( (double x) => x * x ); // outer brackets are not
                                                           // mandatory

(double x) => x * x is an expression. It is not a type, whereas delegates (generic or not) are.

(double x) => x * x是一个表达式。它不是类型,而委托(通用的或非通用的)是。

Morality ? At end, what is a delegate (resp. generic delegate), if not a function pointer type (resp. wrapped+smart+generic function pointer type), huh ? Something else ! See this and that.

道德?最后,什么是委托(resp)。泛型委托),如果不是函数指针类型(resp)。包装+智能+通用函数指针类型),嗯?别的东西!看到这个,。

#16


0  

Some basic here. "Delegate" is actually the name for a variable that holds a reference to a method or a lambda

一些基本的。“Delegate”实际上是一个变量的名称,它包含对方法或lambda的引用

This is a anonymous method - (string testString) => { Console.WriteLine(testString); };

这是一个匿名方法—(string testString) => {Console.WriteLine(testString);};

As anonymous method do not have any name we need a delegate in which we can assign both of these method or expression. For Ex.

由于匿名方法没有任何名称,所以我们需要一个委托,在这个委托中我们可以同时分配这两个方法或表达式。前女友。

delegate void PrintTestString(string testString); // declare a delegate

委托无效PrintTestString(string testString);/ /声明一个委托

PrintTestString print = (string testString) => { Console.WriteLine(testString); }; print();

PrintTestString print = (string testString) => {Console.WriteLine(testString);};print();


Same with the lambda expression. Usually we need delegate to use them

和表达式一样。通常我们需要委托来使用它们

s => s.Age > someValue && s.Age < someValue // will return true/false

= >年代。年龄>岁以上。年龄< someValue //将返回true/false

We can use a func delegate to use this expression.

我们可以使用func委托来使用这个表达式。

Func< Student,bool> checkStudentAge = s => s.Age > someValue && s.Age < someValue ;

Func< Student,bool> checkStudentAge = s => . s。年龄>岁以上。年龄< someValue;

bool result = checkStudentAge ( Student Object);

bool结果= checkStudentAge(学生对象);

#17


-1  

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只是对匿名函数的一种简化。委托可以做的不仅仅是匿名函数:事件、异步调用和多个方法链。