什么是C#λ';s编译成?堆栈帧、匿名类型的实例或

本文关键字:堆栈 类型 实例 编译 什么 | 更新日期: 2023-09-27 18:21:14

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

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

什么是C#λ';s编译成?堆栈帧、匿名类型的实例或

假设你的意思是"作为委托",那么它仍然取决于: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。

Lambda表达式确实是匿名函数,但具有更多的通用性。MSDN撰写的这两篇文章提供了大量关于lambda表达式、如何使用它们、运算符=>的优先级、它们与匿名函数的关系以及一些高级使用建议的信息。

Lambda表达式(MSDN)

=>操作员(MSDN)

以下是一些示例:

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

lambda表达式是一个未命名的方法,用来代替委托istance。编译器将其转换为:

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

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