C# 编译优化:空合并运算符 - 更新 - Reflector 的 bug?
问候!我对 C# 编译器如何执行优化有点困惑。
我编写了以下 getter 来弥补“惰性”初始化,以及 null 情况下的默认值:
静态类助手:
private static string host;
public static string Host
{
get
{
return host ?? (host= (ConfigurationManager.AppSettings["Host"] ?? "host.ru"));
}
}
是 Reflector 反汇编的结果:
public static string Host
{
get
{
if (Helper.host == null)
{
string host = Helper.host;
}
return (Helper.host = ConfigurationManager.AppSettings["Host"] ?? "host.ru");
}
}
这 就像它会以与假设不同的方式工作...
更新
private static string host;
public static string Host
{
get
{
return host ?? (host = (GetVal() ?? "default"));
}
}
static void Main(string[] args)
{
Console.WriteLine(Host);
host = "overwritten";
Console.WriteLine(Host);
}
static string GetVal()
{
return "From config";
}
工作正常(从配置中,覆盖),但 Reflector 显示相同的:
public static string Host
{
get
{
if (Program.host == null)
{
string host = Program.host;
}
return (Program.host = GetVal() ?? "default");
}
}
Greetings! I am slightly confused about how does C# compiler perform its optimizations.
I have written the following getter to make up "lazy" initialization, and default value in case of null:
Static class Helper:
private static string host;
public static string Host
{
get
{
return host ?? (host= (ConfigurationManager.AppSettings["Host"] ?? "host.ru"));
}
}
Here is the result of disassembling by Reflector:
public static string Host
{
get
{
if (Helper.host == null)
{
string host = Helper.host;
}
return (Helper.host = ConfigurationManager.AppSettings["Host"] ?? "host.ru");
}
}
Looks like it would work in other way than assumed...
UPDATE
private static string host;
public static string Host
{
get
{
return host ?? (host = (GetVal() ?? "default"));
}
}
static void Main(string[] args)
{
Console.WriteLine(Host);
host = "overwritten";
Console.WriteLine(Host);
}
static string GetVal()
{
return "From config";
}
Works correctly (From config, overwritten), but Reflector shows the same:
public static string Host
{
get
{
if (Program.host == null)
{
string host = Program.host;
}
return (Program.host = GetVal() ?? "default");
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这看起来像是 Reflector 的 C# 反汇编中的错误。
从这段代码开始:
Reflector 显示了这个 C# 反汇编:
以及相应的 IL:
我不是 IL 专家,但这是我的看法:
L_0000:
ldsfld
推送_test
到评估堆栈L_0005:
dup
复制计算堆栈最顶层的值 (_test
) 并将其推入堆栈。L_0006:
brtrue.s
将dup
创建的值从堆栈中弹出,如果不为null
则跳转到L_0017
>。L_0008:
pop
此时,_test
为null
,因此将该值从堆栈中弹出。它继续以类似的方式评估
_setting
,如果_setting
也是null
,则最终返回"default"
。现在,如果我们在代码中添加一个赋值,如下所示:
Reflector 显示此 C# 反汇编:
这是不正确的(如果
_test
不是null
,而不是返回_test
,它将_setting
或"default"
分配给_test
,然后返回)。但是,IL 反汇编看起来像
Test_1
的 IL,在L_0017
和L_0018
处有一些额外的指令来完成分配。最后,如果您复制 Reflector 的 C# 反汇编并针对原始版本运行它,您将看到它产生不同的结果。
输出
This looks like a bug in Reflector's C# disassembly.
Starting with this code:
Reflector shows this C# disassembly:
and the corresponding IL:
I am not an IL expert, but this is my take on it:
L_0000:
ldsfld
pushes_test
onto the evaluation stackL_0005:
dup
copies the value (_test
) that is topmost on the evaluation stack and pushes that onto the stack.L_0006:
brtrue.s
pops the value created bydup
off the stack and jumps toL_0017
if it is notnull
.L_0008:
pop
at this point,_test
isnull
, so pop that value off the stack.and it continues to evaluate
_setting
in a similar fashion, finally returning"default"
if_setting
is alsonull
.Now, if we add an assignment into the code like this:
Reflector shows this C# disassembly:
which is not correct (if
_test
is notnull
, instead of returning_test
, it assigns_setting
or"default"
to_test
and then returns).However, the IL dissassembly looks like the IL for
Test_1
, with a couple of extra instructions atL_0017
andL_0018
to do the assignment.Finally, if you copy Reflector's C# dissembly and run it against the original, you'll see it produces different results.
Outputs
我想我不明白 - 两个代码示例是同义词。
请记住,Reflector 无法从编译器生成的 IL 中重现您的确切语法。有时语法会有所不同,但代码的语义和含义始终是相同的。
I guess I don't understand - both code examples are synonymous.
Remember that Reflector cannot reproduce your exact syntax from the IL that the compiler generates. Sometimes the syntax will be different but the semantics and meaning of the code will always be the same.