【问题标题】:How to translate or convert CompilerGenerated code?如何翻译或转换编译器生成的代码?
【发布时间】:2014-04-21 10:06:39
【问题描述】:

如果您尝试使用反编译器,例如:jetbrains dotpeek、redgate reflector、telerik justdecompile 等等。有时如果您需要复制代码或只是为了理解,这是不可能的,因为会显示类似的内容:

[CompilerGenerated]
private sealed class Class15
{
    // Fields
    public Class11.Class12 CS$<>8__locals25;
    public string endName;

    // Methods
    public Class15();
    public bool <Show>b__11(object intelliListItem_0);
}

我不关心混淆,这随时都会发生,我做了一些测试(我自己的代码),并且使用 lambdas 和迭代器发生。我不确定,谁能提供更多关于何时以及为什么......的信息?


因此,按照标准 Visual Studio,不要在 c# 中编译 $ 和 关键字(如上面的代码)...
有没有办法自动翻译或转换这个反编译的代码?

【问题讨论】:

    标签: c# .net il decompiler


    【解决方案1】:

    Lambdas 是一种闭包形式,它是一种可以像对象一样传递的代码单元(但可以访问其原始上下文)的一种时髦方式。当编译器找到一个 lambda 时,它会生成一个新类型(Type 是一个类或结构),它封装了 lambda 在其原始上下文中访问的代码和任何字段。

    这里的问题是,如何生成永远不会与用户编写的代码冲突的代码?

    编译器的答案是生成在您使用的语言中非法但在 IL 中合法的代码。 IL 是“中间语言”,它是公共语言运行时使用的母语。在 CLR(C#、vb.net、F#)上运行的任何语言都可以编译成 IL。这就是您在 C# 代码等中使用 VB.Net 程序集的方式。

    所以这就是反编译器生成你看到的可怕代码的原因。迭代器遵循与许多其他需要生成类型的语言特性完全相同的模型。

    有一个有趣的副作用。 Lambda 可以在其原始上下文中捕获变量:

    public void TestCapture()
    {
        StringBuilder b = new StringBuilder();
        Action l = () => b.Append("Kitties!");
    
    }
    

    所以捕获我的意思是这里的变量 b 包含在定义闭包的包中。

    编译器试图提高效率并创建尽可能少的类型,因此您最终可以生成一个支持在特定类中找到的所有 lambdas 的生成类,包括所有捕获变量的字段。这样一来,如果你不小心,你可能会意外捕获你期望被释放的东西,从而导致跟踪内存泄漏非常棘手。

    【讨论】:

    • 好答案。顺便说一句,大多数现代反编译器都非常擅长识别这些模式并恢复原始高级代码,无论是 lambdas 还是自定义迭代器 (yield)。如果反编译器配置为 C# 3+ 语言级别并且没有明确启用“显示编译器生成的代码”之类的功能,则看到这些工件可能表明程序集是使用非 Microsoft 编译器编译的或通过某种方式运行的重写器(例如,出于 AOP 目的)。此外,this answer 列出了许多由 csc.exe 发出的生成名称。
    • 是的,你知道我在几个小时后重读了我写的内容,并意识到我实际上忘记回答最初的问题,尽管你添加了很多我不知道的内容:)
    • @Ian 你能回答实际问题吗?我实际上也对如何做到这一点感兴趣。
    【解决方案2】:

    是否有更改目标框架的选项?...我知道一些反编译器默认为最低级别的框架(C# 1.0)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-05-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-22
      • 2012-10-17
      相关资源
      最近更新 更多