让我们比较两段代码:
String str = null;
//Possibly do something...
str = "Test";
Console.WriteLine(str);
和
String str;
//Possibly do something...
str = "Test";
Console.WriteLine(str);
我一直在想这些代码是平等的。但是在我构建这些代码(检查了优化的发布模式)并比较生成的IL方法后,我注意到第一个样本中还有两个IL指令:
第一个示例代码IL:
.maxstack 1
.locals init([0] string str)
IL_0000:ldnull
IL_0001:stloc.0
IL_0002:ldstr“测试”
IL_0007:stloc.0
IL_0008:ldloc.0
IL_0009:call void [mscorlib] System.Console :: WriteLine(string)
IL_000e:ret
第二个示例代码IL:
.maxstack 1
.locals init([0] string str)
IL_0000:ldstr“测试”
IL_0005:stloc.0
IL_0006:ldloc.0
IL_0007:call void [mscorlib] System.Console :: WriteLine(string)
IL_000c:ret
可能这个代码是由JIT compiller优化的? 那么带有null的本地bethod变量的初始化会影响性能(我知道这是非常简单的操作,但无论如何)我们应该避免它吗? 先谢谢。
答案 0 :(得分:7)
http://www.codinghorror.com/blog/2005/07/for-best-results-dont-initialize-variables.html
总结一下这篇文章,在运行各种基准测试之后,将对象初始化为一个值(作为定义的一部分,在类的构造函数中,或作为初始化方法的一部分)可以是大约10-35在.NET 1.1和2.0上慢了%。较新的编译器可以优化定义的初始化。本文最后建议避免初始化作为一般规则。
答案 1 :(得分:6)
编写清晰代码(无论对您意味着什么)的价值远远超过成本与收益方面的0.00001ms性能提升。这就是为什么首先存在C#和其他高级语言的原因。
我认为这可能是一个学术问题,我并不打算理解CLR内部的价值。但在这种情况下,重点关注似乎是错误的。
答案 2 :(得分:0)
今天(2019年),. NET Framework和.NET Core 编译器都足够聪明,可以优化不必要的初始化。 (以及无用的stloc.0
-ldloc.0
对。)
两个版本都编译为
.maxstack 8
ldstr "Test"
call void [System.Console]System.Console::WriteLine(string)
ret
请参阅我的SharpLab experiment作为参考。
但是当然实现会发生变化,但是贾斯汀的答案是永恒的:我出于好奇而进行了此实验,在实际情况下,我专注于代码的清晰性和表达性,而忽略了微优化。