什么是C#lambda编译成的? 一个堆栈框架,一个匿名类型的实例,或?

什么是C#lambda编译成的? 一个堆栈框架,一个匿名类型的实例,或?

我读过这个问题 。 这主要回答“为什么”在使用隐式类型function时不能使用lambda。 但是,这个问题的目的是回答编译器生成的构造实际执行lambda的代码。 它是一个匿名类型的方法调用(类似于在Java中实现接口的匿名类型吗?),还是只是一个堆栈框架,它引用了闭合变量并接受了参数签名? 有些lambda不会关闭任何东西 – 因此编译中有两个不同的结果输出。

假设你的意思是“作为一个委托”,那么它仍然取决于:p如果它捕获任何变量(包括“this”,这可能是隐含的)那么这些变量实际上是作为编译器生成的类型的字段实现的(不公开任何地方),语句体成为该捕获类的方法。 如果有多个捕获级别,则外部捕获也是内部捕获类的字段。 但基本上:

int i = ... Func func = x => 2*x*i; 

就好像;

 var capture = new SecretType(); capture.i = ... Func func = capture.SecretMethod; 

哪里:

 class SecretType { public int i; public int SecretMethod(int x) { return 2*x*i; } } 

这与“匿名方法”相同,但语法不同。

请注意,不捕获状态的方法可以实现为没有捕获类的静态方法。

另一方面,表达树……解释起来比较棘手:p

但是(我没有编译器,所以请耐心等待):

 int i = ... Expression> func = x => 2*x*i; 

是这样的:

 var capture = new SecretType(); capture.i = ... var p = Expression.Parameter("x", typeof(int)); Expression> func = Expression.Lambda>( Expression.Multiply( Expression.Multiply(Expression.Constant(2),p), Expression.PropertyOrField(Expression.Constant(capture), "i") ), p); 

(除了使用不存在的“memberof”构造,因为编译器可以作弊)

表达式树很复杂,但可以解构和检查 – 例如转换为TSQL。

Lambda表达式确实是匿名函数,但具有更多function。 这两篇由MSDN撰写的文章有很多关于lambda表达式的信息,如何使用它们,operator =>有什么优先级,它们与匿名函数的关系是什么,以及一些高级的使用建议。

Lambda表达式(MSDN)

=>运营商(MSDN)

这里有些例子:

 public class C { private int field = 0; public void M() { int local = 0; Func f1 = () => 0; // f1 is a delegate that references a compiler-generated static method in C Func f2 = () => this.field; // f2 is a delegate that references a compiler-generated instance method in C Func f3 = () => local; // f3 is a delegate that references an instance method of a compiler-generated nested class in C } } 

lambda表达式是一种代替委托代理的未命名方法。 编译器将其转换为:

  • 委托实例
  • Expression类型的表达式树 ,表示可遍历对象模型中的代码。 这允许在运行时解释lambda表达式。

因此,编译器解决了将表达式代码移动到私有方法中的lambda表达式。