如何翻译或转换编译器生成的代码

本文关键字:编译器 代码 转换 何翻译 翻译 | 更新日期: 2023-09-27 17:50:31

如果您尝试使用反编译器,如: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);
}

我不是在谈论混淆,这是随时发生的,我做了一些测试(我自己的代码),并使用lambda和迭代器发生。我不确定,谁能提供更多关于时间和原因的信息?


所以,根据标准Visual Studio不编译c#中的$和<>关键字(如上面的代码)…
有一种方法可以自动翻译或转换此反编译代码吗?

如何翻译或转换编译器生成的代码

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

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

编译器的答案是生成的代码在你使用的语言中是非法的,但在IL中是合法的。IL是"中间语言",它是公共语言运行库使用的本地语言。任何在CLR上运行的语言(c#, vb.net, f#)都可以编译成IL。这就是如何使用VB。. Net程序集,c#代码等等。

所以这就是为什么反编译器生成你看到的丑陋代码。迭代器和其他一些需要生成类型的语言特性遵循完全相同的模型。

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

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

这里的捕获是指变量b包含在定义闭包的包中。

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

是否有更改目标框架的选项?我知道有些反编译器默认使用最底层框架(c# 1.0)