【问题标题】:What does Lambda Expression Compile() method do?Lambda 表达式 Compile() 方法有什么作用?
【发布时间】:2011-12-28 22:45:22
【问题描述】:

我正在尝试理解 C# 中的 AST。我想知道,这个示例中的 Compile() 方法到底是做什么的。

// Some code skipped    
Expression<Func<string, int, int, string>> data = Expression.Lambda<Func<string, int, int, string>>( 
        Expression.Call(s, typeof(string).GetMethod(“Substring”, new Type[] { typeof(int), typeof(int) }), a, b), 
        s, a, b 
    ); 
Func<string, int, int, string> fun = data.Compile(); 

为防止误解,我了解Expression.LambdaExpression.Call 构造。我感兴趣的是Compile() 方法。它会以某种方式产生真正的 MSIL 吗?我可以看到 MSIL 吗?

【问题讨论】:

    标签: c# lambda compilation abstract-syntax-tree


    【解决方案1】:

    我感兴趣的是Compile() 方法。它会以某种方式产生真正的 MSIL 吗?

    是的。 Compile 方法在 lambda 主体块上运行一个访问者,并为每个子表达式动态生成 IL。

    如果您有兴趣学习如何自己吐 IL,请参阅this "Hello World" example of how to use Lightweight Codegen。 (我注意到,如果您不幸不得不在部分受信任的应用程序域中使用轻量级 Codegen,那么在具有受限跳过可见性的世界中,事情可能会变得有些奇怪;如果您感兴趣,请参阅 Shawn Farkas's article。)

    我可以查看 MSIL 吗?

    是的,但您需要一个特殊的“可视化工具”。我在实现我的部分时用来调试Compile() 的可视化工具可以在这里下载:

    http://blogs.msdn.com/b/haibo_luo/archive/2005/10/25/484861.aspx

    【讨论】:

      【解决方案2】:

      这个问题的答案现在已经部分过时了,因为现在只是有时会发生这种情况。

      将表达式编译为 IL 需要 Reflection.Emit,但并非始终可用,尤其是 AOT。因此,在这些情况下,表达式不是编译为 IL,而是“编译”为表示指令的对象列表。这些指令中的每一个都有一个Run 方法,该方法导致它执行适当的操作,对堆栈值进行处理,就像IL 在堆栈上工作一样。然后可以将在这些对象上调用 Run 的方法作为委托返回。

      通常运行这样的委托比 jitting IL 慢,但它是编译到 IL 不可用时的唯一选择,并且编译步骤通常更快,因此编译 + 运行的总时间通常更少解释器而不是使用 IL 来处理一次性表达式。

      因此,在 .NET Core 中,现在有一个 Compile 的重载,即使编译为 IL 可用,它也会接受布尔请求解释。

      所有这些都构成了一种有趣的语言组合;表达式本身是一种语言,程序集是用C#编写的,可以编译成IL,解释的指令对象构成第四种语言。

      【讨论】:

        【解决方案3】:

        Expression 以表达式树的形式表示数据结构 - 使用Compile(),此表达式树可以编译为委托形式的可执行代码(这是一种“方法”调用)。

        编译后,您通常可以调用委托 - 在您的示例中,委托是 Func&lt;string,int,int,string&gt;。当您基于仅在运行时可用的数据动态创建表达式树时,可能需要此方法,最终目标是创建和执行相应的委托。

        您看不到代表的“代码”。它所基于的表达式树本身是最接近的。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-05-17
          • 1970-01-01
          相关资源
          最近更新 更多