C#lambda编译成什么? stackframe,匿名类型的实例,或?
我已经读过question了。这主要回答“为什么”在使用隐式类型功能时不能使用lambda。但是,这个问题的目的是回答编译器生成的构造实际执行lambda的代码。它是一个匿名类型的方法调用(类似于在Java中实现接口的匿名类型吗?),还是只是一个堆栈框架,它引用了闭合变量并接受了参数签名?有些lambda不会关闭任何东西 - 因此编译中有两个不同的结果输出。
答案 0 :(得分:17)
假设你的意思是“作为委托”,那么它仍然取决于:p如果它捕获任何变量(包括“this”,这可能是隐含的)那么这些变量实际上是作为编译器生成的类型的字段实现的(不是暴露在任何公共场所),语句体成为该捕获类的方法。如果有多个捕获级别,则外捕获也是内捕获类的一个字段。但基本上是:
int i = ...
Func<int,int> func = x => 2*x*i;
就像;
var capture = new SecretType();
capture.i = ...
Func<int,int> func = capture.SecretMethod;
其中:
class SecretType {
public int i;
public int SecretMethod(int x) { return 2*x*i; }
}
这与“匿名方法”相同,但语法不同。
请注意,不捕获状态的方法可以实现为没有捕获类的静态方法。
另一方面,表达树......解释起来比较棘手:p
但是(我手边没有编译器,所以请耐心等待):
int i = ...
Expression<Func<int,int>> func = x => 2*x*i;
类似于:
var capture = new SecretType();
capture.i = ...
var p = Expression.Parameter("x", typeof(int));
Expression<Func<int,int>> func = Expression.Lambda<Func<int,int>>(
Expression.Multiply(
Expression.Multiply(Expression.Constant(2),p),
Expression.PropertyOrField(Expression.Constant(capture), "i")
), p);
(除了使用不存在的“memberof”构造,因为编译器可以作弊)
表达式树很复杂,但可以解构和检查 - 例如转换为TSQL。
答案 1 :(得分:1)
Lambda表达式确实是匿名函数,但具有更多功能。这两篇由MSDN撰写的文章有很多关于lambda表达式的信息,如何使用它们,运算符=>
具有什么优先级,它们与匿名函数的关系是什么,以及一些高级使用建议。
答案 2 :(得分:1)
以下是一些例子:
public class C
{
private int field = 0;
public void M()
{
int local = 0;
Func<int> f1 = () => 0;
// f1 is a delegate that references a compiler-generated static method in C
Func<int> f2 = () => this.field;
// f2 is a delegate that references a compiler-generated instance method in C
Func<int> f3 = () => local;
// f3 is a delegate that references an instance method of a compiler-generated nested class in C
}
}
答案 3 :(得分:1)
lambda表达式是一种代替委托代理的未命名方法。 编译器将其转换为:
Expression<TDelegate>
,表示可遍历对象模型中的代码。这允许在运行时解释lambda表达式。 因此,编译器解决了将表达式代码移动到私有方法中的lambda表达式。