在编写我的库时,我使用了一系列三元表达式:
但是,当我反编译代码时,我发现它变成了一个糟糕的实现(在我看来):
当我测试我的代码时,测试通过了:
我不明白为什么反编译器产生的输出与我最初编写的不同,而且,我不确定我是否理解如何编写高效的代码。
为什么我的编译器生成的 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
似乎是更合适的结构。例如:
return txt switch
{
"-" => Substruction(...),
"+" => Addition(),
// ...
_ => number
}
想必您正在查看反编译器的输出。
反编译器根据程序集的 CIL/MSIL(也称为字节码)生成代码。这与 C# 等高级语言没有 1:1 的关系。
ECMA-335 第三部分包含 CIL 的定义。
研究CIL你会发现没有“三元运算符”指令这样的东西。因此,反编译器会生成看起来像简单比较的代码(
if
语句)。
从根本上来说,一系列
if
语句和三元表达式在运行时是相同的,这两者在中间语言和机器语言中没有区别。
一些反编译器可能会使用 PDB/Debug 信息来帮助生成原始代码,这可能允许反编译器生成三元表达式作为输出,但这本质上是“作弊”,因为无法知道程序员是否使用了三元表达式仅基于 IL 的表达。
您可以使用ildasm等工具来检查代码的IL。
愤怒的暴徒会对你的问题投接近票,因为他们只知道如何仇恨,而不是教导。希望这个答案可以帮助您或其他像您一样有类似问题的人。