声明为 readonly 的成员可以在类的(静态)构造函数中进行更改,而 const 成员不能在运行时更改。
将字段声明为 const 使其自动成为静态,引用 §10.3.7:
当字段、方法、属性、事件、运算符或构造函数声明包含静态修饰符时,它声明一个静态成员。此外,常量或类型声明隐式声明了一个静态成员。
第三个只是一个只读属性,它恰好总是返回 5。
您永远不应该使用这样的属性并尽可能选择 const 成员,以允许编译器和/或抖动执行优化并帮助其他人阅读您的代码(该属性对我来说是一种 WTF)。如果需要在程序启动期间初始化一个常量值(例如,机器的内核数),则必须使用静态只读成员。
这是来自 C# 规范(§10.5.2.1)的一个很好的例子:
当需要常量值的符号名称,但在 const 声明中不允许该值的类型,或者无法在编译时计算该值时,静态只读字段很有用。在示例中
public class Color
{
public static readonly Color Black = new Color(0, 0, 0);
public static readonly Color White = new Color(255, 255, 255);
public static readonly Color Red = new Color(255, 0, 0);
public static readonly Color Green = new Color(0, 255, 0);
public static readonly Color Blue = new Color(0, 0, 255);
private byte red, green, blue;
public Color(byte r, byte g, byte b) {
red = r;
green = g;
blue = b;
}
}
Black、White、Red、Green 和 Blue 成员不能声明为 const 成员,因为它们的值不能在编译时计算。但是,将它们声明为 static readonly 具有相同的效果。
还有另一个区别(§10.5.2.2):
常量和只读字段具有不同的二进制版本语义。当表达式引用一个常量时,该常量的值是在编译时获得的,但是当一个表达式引用一个只读字段时,该字段的值直到运行时才获得。
所以,总而言之,它们是非常不同的,即使乍一看它们可能看起来很相似,你应该使用最适合你意图的那个。