如果我可以投票支持,我会支持Jon Skeet的答案。另外,就像在IL中展示的那样,您的#1和#2完全相同:
.method public hidebysig specialname instance string
get_SomeConstant() cil managed
{
// Code size 11 (0xb)
.maxstack 1
.locals init ([0] string CS$1$0000)
IL_0000: nop
IL_0001: ldstr "string that will never change"
IL_0006: stloc.0
IL_0007: br.s IL_0009
IL_0009: ldloc.0
IL_000a: ret
} // end of method Class1::get_SomeConstant
选项 #2:
.method public hidebysig specialname instance string
get_SomeConstant() cil managed
{
// Code size 11 (0xb)
.maxstack 1
.locals init ([0] string CS$1$0000)
IL_0000: nop
IL_0001: ldstr "string that will never change"
IL_0006: stloc.0
IL_0007: br.s IL_0009
IL_0009: ldloc.0
IL_000a: ret
} // end of method Class2::get_SomeConstant
现在看看选项#3。 3号与#1和#2非常不同。 这是因为,如先前所述,#3是静态的,因为const是静态的。 现在真正的问题是要将苹果与苹果进行比较,即如果#1和#2是静态访问器怎么办? 那么它们将更可比于#3。 目前,您必须初始化选项1和2的类,但不需要初始化#3。 因此,在这种情况下存在不必要的对象初始化,并且您始终希望尽可能使用静态,以避免出现这种情况。
现在让我们看看IL中的第3个数字:
.field public static literal string SomeConstant = "string that will never change"
因此,为了效率,我会使用#3。这也是多年来许多才华横溢的同行教给我的。
现在,解决一个显而易见的问题。Readonly和const不同之处在于const在编译时出现,而readonly在运行时出现。静态readonly只初始化一次,而非静态readonly每个实例初始化一次。例如,如果您要创建一个包含永远不会更改的const字符串的类用于错误消息,则应使用选项#3,而不是readonly static或其他选项。想象一下在运行时初始化数百条错误消息,而不是在编译时,您将看到明显的性能差异。此外,由于您明确指出它是“永远不会更改”的字符串,在这种情况下甚至不应考虑readonly,因为“……它永远不会更改”。Const和ReadOnly有其位置,但对于从不更改且在编译时已知的项目,不应使用readonly。