在C#中常量和只读之间有什么区别?

你什么时候会用一个代替另一个?


当前回答

还有一个陷阱:只读值可以通过反射被“狡猾”的代码改变。

var fi = this.GetType()
             .BaseType
             .GetField("_someField", 
                       BindingFlags.Instance | BindingFlags.NonPublic);
fi.SetValue(this, 1);

我可以使用反射更改C#中的私有只读继承字段吗?

其他回答

我们办公室的一名团队成员就何时使用常量、静态和只读提供了以下指导:

当您有一个在运行时可以知道的类型的变量(string literal、int、double、enums…),您希望类的所有实例或使用者都可以访问值不应更改的位置时,请使用const。如果您希望类的所有实例或使用者都可以访问值可以更改的数据,请使用静态。当您有一个在运行时无法知道的类型的变量(对象),您希望类的所有实例或使用者都可以访问值不应更改的位置时,请使用静态只读。当您有一个实例级变量时,您将在创建对象时知道该变量不应更改,请使用readonly。

最后一个注意事项:常量字段是静态的,但反之则不是真的。

不同之处在于,静态只读字段的值是在运行时设置的,因此对于程序的不同执行,它可以具有不同的值。但是,const字段的值设置为编译时常量。

记得:对于引用类型,在这两种情况下(静态和实例),只读修饰符只会阻止您将新引用分配给字段。它特别地不使引用指向的对象不可变。

有关详细信息,请参阅有关此主题的C#常见问题解答:http://blogs.msdn.com/csharpfaq/archive/2004/12/03/274791.aspx

const是编译时常量,而readonly允许在运行时计算值并在构造函数或字段初始值设定项中设置。因此,“const”总是常量,但“readonly”在赋值后是只读的。

C#团队的埃里克·里佩尔(Eric Lippert)有更多关于不同类型不变性的信息。

标记为const的变量只不过是强类型的#define宏,在编译时,const变量引用被替换为内联文本值。因此,只能以这种方式使用某些内置基元值类型。标记为只读的变量可以在运行时在构造函数中设置,并且它们的只读性也在运行时强制执行。与此相关的性能开销较小,但这意味着您可以对任何类型(甚至引用类型)使用只读。

此外,常量变量本质上是静态的,而只读变量如果需要可以是特定于实例的。

有一个与常量的gotcha!如果从另一个程序集引用常量,则其值将直接编译到调用程序集中。这样,当您更新引用程序集中的常量时,它不会在调用程序集中发生更改!