仅使用私有变量时,与常规可修改字段相比,使用
const
或 readonly
字段是否有任何性能优势?
例如:
public class FooBaar
{
private string foo = "something";
private const string baar = "something more"
public void Baaz()
{
//access foo, access baar
}
}
在上面的示例中,您可以看到有两个字段:
foo
和baar
。两者在课堂之外都无法访问,所以为什么很多人更喜欢在这里使用const
,而不是仅仅使用private
。 const
是否提供任何性能优势?
这个问题之前被社区关闭了,因为人们把这个问题误解为“
const
和readonly
在性能方面有什么区别?”,已经在这里回答了:之间有什么区别const 和只读?.const
或 readonly
与不使用其中任何一个相比,我是否能获得任何性能优势”。
const 会被编译器优化以内联到代码中,而 readonly 不能内联。但是,您不能创建所有类型的常量 - 因此在这里您必须将它们设置为只读。
因此,如果您的代码中需要一个常量值,您应该首先考虑使用 const(如果可能的话),如果没有,那么 readonly 可以让您获得安全性,但不会获得性能优势。
举个例子:
public class Example
{
private const int foo = 5;
private readonly Dictionary<int, string> bar = new Dictionary<int, string>();
//.... missing stuff where bar is populated
public void DoSomething()
{
Console.Writeline(bar[foo]);
// when compiled the above line is replaced with Console.Writeline(bar[5]);
// because at compile time the compiler can replace foo with 5
// but it can't do anything inline with bar itself, as it is readonly
// not a const, so cannot benefit from the optimization
}
}
我也有同样的疑问,并且我使用了一个工具来检查使用静态和只读修饰符所产生的 IL 输出。
检查这个例子:
public class C {
const string test = "stuff";
private static string test2 = "stuff2";
public static void M() {
System.Console.WriteLine(test);
System.Console.WriteLine(test2);
}
}
M() 的 IL 输出:
IL_0000: nop
IL_0001: ldstr "stuff"
IL_0006: call void [System.Console]System.Console::WriteLine(string)
IL_000b: nop
IL_000c: ldsfld string C::test2
IL_0011: call void [System.Console]System.Console::WriteLine(string)
IL_0016: nop
IL_0017: ret
它不太可能在当前的硬件中产生任何性能差异,但是当CPU执行指令时,常量似乎会将数据携带到word中,而静态引用将携带一个内存指针,这将使CPU 检索某些寄存器/L1 缓存等中的值。
此处的完整输出:https://gist.github.com/VagnerGon/e8f48a652cc4f234c2ab060a5eeb7d2e
我不会太担心这些构造的性能,直到您遇到一段需要您进行此类测量的关键代码。它们的作用是确保代码的正确性,而不是出于性能原因。