Reed Copsey 说为字段指定默认值会影响性能,他指的是 2005 年的一项测试。
public class A
{
// Use CLR's default value
private int varA;
private string varB;
private DataSet varC;
}
public class B
{
// Specify default value explicitly
private int varA = 0;
private string varB = null;
private DataSet varC = null;
}
现在八年了,四个版本的 C# 和 .NET 之后我决定在 .NET Framework 4.5 和 C# 5 下重复该测试,使用 Visual Studio 2012 编译为具有默认优化的 Release。我惊讶地发现仍然存在性能差异在使用默认值显式初始化字段和不指定默认值之间。我本来希望后来的 C# 编译器现在可以优化那些常量赋值。
无初始化:512,75 默认初始化:536,96 常量初始化:720,50
方法无初始化:140,11 Def 方法初始化:166,86
(其余)
所以我在类的构造函数A
和B
这个测试中偷看了一下,两者都是空的:
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method .ctor
我在 IL 中找不到为什么显式为字段分配默认常量值会消耗更多时间的原因。显然 C# 编译器确实优化了常量,我怀疑它总是这样做的。
所以,那么测试一定是错误的......我交换了 classesA
和的内容B
,交换了结果字符串中的数字,然后重新运行了测试。你瞧,现在突然指定默认值更快了。
无初始化:474,75 默认初始化:464,42 常量初始化:715,49
方法无初始化:141,60 方法初始化在 Def:171,78
(其余)
因此,我得出结论,C# 编译器正确优化了您为字段分配默认值的情况。它没有性能差异!
现在我们知道性能真的不是问题。我不同意Reed Copsey 的说法“ ‘额外’代码,即使它是无害的,表明它的存在是有原因的,这会降低可维护性。 ”并同意Anders Hansson的观点:
考虑长期维护。
- 保持代码尽可能明确。
- 如果不需要,不要依赖语言特定的初始化方式。也许新版本的语言会以不同的方式工作?
- 未来的程序员会感谢你。
- 管理层会感谢你的。
- 为什么要混淆事物,哪怕是最轻微的?
未来的维护者可能来自不同的背景。这真的不是关于什么是“正确的”,而是从长远来看最容易的事情。