在C#中常量和只读之间有什么区别?
你什么时候会用一个代替另一个?
在C#中常量和只读之间有什么区别?
你什么时候会用一个代替另一个?
当前回答
const是编译时常量,而readonly允许在运行时计算值并在构造函数或字段初始值设定项中设置。因此,“const”总是常量,但“readonly”在赋值后是只读的。
C#团队的埃里克·里佩尔(Eric Lippert)有更多关于不同类型不变性的信息。
其他回答
有一个与常量的gotcha!如果从另一个程序集引用常量,则其值将直接编译到调用程序集中。这样,当您更新引用程序集中的常量时,它不会在调用程序集中发生更改!
下面是另一个链接,演示const如何不是版本安全的,或者与引用类型无关。
摘要:
const属性的值在编译时设置,不能在运行时更改Const不能被标记为静态的-关键字表示它们是静态的,而只读字段则可以。Const不能是除值(基元)类型以外的任何类型readonly关键字将字段标记为不可更改。但是,属性可以在类的构造函数内更改readonly关键字还可以与static组合,使其以与常量相同的方式(至少在表面上)起作用。当你观察两者之间的IL时,有一个显著的差异常量字段在IL中标记为“literal”,而readonly为“initonly”
除了
必须在常量VS只读值的定义时声明该值可以动态计算,但需要在构造函数退出之前赋值。之后,它被冷冻。常量是隐式静态的。您使用ClassName.ConstantName符号来访问它们。
有一个微妙的区别。考虑AssemblyA中定义的类。
public class Const_V_Readonly
{
public const int I_CONST_VALUE = 2;
public readonly int I_RO_VALUE;
public Const_V_Readonly()
{
I_RO_VALUE = 3;
}
}
AssemblyB引用AssemblyA并在代码中使用这些值。编译时:
对于常量值,它就像查找替换。值2被“烘焙”到AssemblyB的IL中。这意味着如果明天我将I_CONST_value更新为20,AssemblyB仍将有2,直到我重新编译它。在只读值的情况下,它类似于对内存位置的引用。该值不会烘焙到AssemblyB的IL中。这意味着如果更新了内存位置,AssemblyB将在不重新编译的情况下获得新值。因此,如果I_RO_VALUE更新为30,则只需要构建AssemblyA,而不需要重新编译所有客户端。
因此,如果你确信常数的值不会改变,那么使用常量。
public const int CM_IN_A_METER = 100;
但是,如果您有一个可能会改变的常数(例如w.r.t.精度),或者当有疑问时,请使用只读。
public readonly float PI = 3.14;
更新:阿库需要被提及,因为他首先指出了这一点。此外,我需要插入我学到的内容:有效的C#-比尔·瓦格纳
标记为const的变量只不过是强类型的#define宏,在编译时,const变量引用被替换为内联文本值。因此,只能以这种方式使用某些内置基元值类型。标记为只读的变量可以在运行时在构造函数中设置,并且它们的只读性也在运行时强制执行。与此相关的性能开销较小,但这意味着您可以对任何类型(甚至引用类型)使用只读。
此外,常量变量本质上是静态的,而只读变量如果需要可以是特定于实例的。
常量必须是硬编码的,其中可以在类的构造函数中设置为只读。