Lambda表达式定义(pedant)?

时间:2012-12-20 12:48:07

标签: c# .net delegates lambda

通过简单介绍一本书(领先一本),有一件事引起了我的注意 - lambda表达式定义:

  

lambda表达式是一个用来代替a的未命名方法   委托实例。

代替委托实例???

委托实例是对象,它引用/封装目标方法:

在以下示例中右侧(lambda表达式所在的位置)不是委托实例。这是一种方法。

TransformerDelegate t = SquareMethod;

所以定义应该更正/提及:

  

lambda表达式是用来代替方法编写的未命名方法(!)   由委托变量引用。

TransformerDelegate sqr = x => x * x;
                              ^
                              |
               ---------------+
               |

            this is the location for method/anonymous methods.
你知道我的意思吗?我是对的吗?

P.S。我 了解msdn的一个:(但想知道这本书是否犯了错误)

  

lambda表达式是一个可以包含的匿名函数   表达式和语句,可用于创建委托或   表达式树类型。

3 个答案:

答案 0 :(得分:4)

lambda表达式的值是委托实例。

所以这本书可能指的是代码:

MySquareDelegate f1 = x => x * x;
MySquareDelegate f2 = new MySquareDelegate(MySquareMethod);
MySquareDelegate f3 = MySquareMethod;  // just shorthand for the previous line

用1句话解释你自己的版本

是一件很棘手的事情
  

lambda表达式是代替由委托变量引用的方法(!)而编写的未命名方法。

正在讨论“方法而不是方法”,原文关于“方法而不是委托实例”,其中方法被隐式转换为委托实例。两者似乎至少都不完整。

lambda的定义还应包括它是内联方法。

答案 1 :(得分:1)

其他答案错过了lambda表达式不一定代表方法的事实。有时,它们代表表达树。

编译器隐式地将lambda表达式转换为一种对象或另一种对象,具体取决于上下文。

要指定方法,您需要指定参数和正文。在lambda表达式中,它们由=>分隔。例子:

    ()     => 4;               //empty parameter list
    x      => x.ToString();    //one parameter
    (a, b) => a.Equals(b);     //two parameters
//  ^^^^^^    ^^^^^^^^^^^^
//  |                    |
//  parameter list       body

这些lambda表达式可以分别转换为Func<int>Func<object, string>Func<object, object, bool>。也可以分别转换为Expression<Func<int>>Expression<Func<object, string>>Expression<Func<object, object, bool>>

匿名方法:

delegate (object p, object q) { return string.Concat(p, q); }
//       ^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//       parameter list       body

以下是lambda转换的两个例子:

Func<object, object, bool> aDelegate = (o1, o2) => object.Equals(o1, o2);
Expression<Func<object, object, bool>> anExpressionTree = (o1, o2) => object.Equals(o1, o2);

在方法组转换中,参数和方法体由重载决策指定。为简化一点,编译器会查看具有指定名称的方法,并根据上下文选择正确的重载。例如,考虑SquareMethod的这些重载:

int SquareMethod(int a) { return a * a; }
double SquareMethod(double a) { return a * a; } 

这些语句涉及方法组转换和重载解析:

Func<int, int> squareAnInt = SquareMethod;
Func<double, double> squareADouble = SquareMethod;

最后,语句lambdas无法转换为表达式树:

Action<object> anAction = o => { Console.WriteLine(o); };
Func<object, int> aFunc = o =>
    {
        var s = (o ?? "").ToString();
        Console.WriteLine(s);
        return s.Length;
    };

C#语言规范(有点令人困惑)使用术语“匿名函数”来涵盖lambda表达式和匿名方法。匿名函数可以隐式转换为兼容的委托类型,方法组也可以。因此,如果我们有一个名为DelegateType的委托类型,并且声明/赋值如下:

DelegateType d = [something];

然后[something]可以是方法组或匿名函数。换句话说,它可以是方法组,匿名方法或lambda表达式。

所以,你对书中文本的修正会更好地说“代替一个方法组”,但我会说

  

lambda表达式是一个未命名的方法,与命名方法组一样,可用于创建委托实例。

我可能还会添加

  

在某些情况下,lambda表达式可用于创建表达式树而不是委托实例。

答案 2 :(得分:0)

基本上,委托只不过是一个知道如何调用特定方法的对象。因此委托实例字面上充当调用者的委托:调用者调用委托,然后委托调用目标方法。