在编写我的库时,我使用了一系列三元表达式:
public INumber Level1()
{
INumber number = Level2();
Next();
return
txt == "-" ?
new Subtraction(number, Level1()) :
txt == "+" ?
new Addition(number, Level1()) :
txt == "/" ?
new Division(number, Level1()) :
txt == "*" ?
new Multiplication(number, Level1()) :
number;
}
但是,当我反编译代码时,我发现它变成了一个糟糕的实现(在我看来):
public INumber Level1()
{
INumber number = Level2();
Next();
if (!(txt == "-"))
{
if (!(txt == "+"))
{
if (!(txt == "/"))
{
if (!(txt == "*"))
{
return number;
}
else
{
INumber number2 = new Multiplication(number, Level1());
result = number2;
}
}
else
{
INumber number2 = new Division(number, Level1());
result = number2;
}
}
else
{
INumber number2 = new Addition(number, Level1());
result = number2;
}
}
else
{
INumber number2 = new Subtraction(number, Level1());
result = number2;
}
return result;
}
当我测试我的代码时,测试通过了。
我不明白为什么反编译器产生的输出与我最初编写的不同,而且,我不确定我是否理解如何编写高效的代码。
为什么反编译器生成的 C# 与我编写的不同,我应该做些什么来改变它?
我不明白为什么会这样
编译器会将你的代码翻译成IL(中间语言),据我所知,这是反编译器的一个怪癖。例如以下内容:
public class C {
public int M(string txt) => txt == "1"
? 1
: txt == "2"
? 2
: 3;
}
翻译为:
IL_0000: ldarg.1
IL_0001: ldstr "1"
IL_0006: call bool [System.Runtime]System.String::op_Equality(string, string)
IL_000b: brtrue.s IL_001e
IL_000d: ldarg.1
IL_000e: ldstr "2"
IL_0013: call bool [System.Runtime]System.String::op_Equality(string, string)
IL_0018: brtrue.s IL_001c
IL_001a: ldc.i4.3
IL_001b: ret
IL_001c: ldc.i4.2
IL_001d: ret
IL_001e: ldc.i4.1
IL_001f: ret
brtrue.s
代码不会逆转条件。但是多种语言结构可能会导致相同的 IL,因此反编译器需要做一些猜测工作,从而得到您看到的结果。
现在我不明白如何正确编写代码 是否有可能修复它
写得正确,不需要“修复”。至少在某种程度上。
但我没有对布尔值进行反转。
你不应该打扰,编译器应该生成正确的代码(至少通常是这样)。如果您愿意 - 编写一个单元测试来验证行为。
最后但并非最不重要的一点。在这种特殊情况下,
switch
(语句或表达式)似乎是更合适的结构。例如通过 switch
表达式:
return txt switch
{
"-" => Substruction(...),
"+" => Addition(...),
// ...
_ => number
}
想必您正在查看反编译器的输出。
反编译器根据程序集的 CIL/MSIL(也称为字节码)生成代码。这与 C# 等高级语言没有 1:1 的关系。
ECMA-335 第三部分包含 CIL 的定义。
研究CIL你会发现没有“三元运算符”指令这样的东西。因此,反编译器会生成看起来像简单比较的代码(
if
语句)。
从根本上来说,一系列
if
语句和三元表达式在运行时是相同的,这两者在中间语言和机器语言中没有区别。
一些反编译器可能会使用 PDB/Debug 信息来帮助生成原始代码,这可能允许反编译器生成三元表达式作为输出,但这本质上是“作弊”,因为无法知道程序员是否使用了三元表达式仅基于 IL 的表达。
您可以使用ildasm等工具来检查代码的IL。