在C#中常量和只读之间有什么区别?
你什么时候会用一个代替另一个?
在C#中常量和只读之间有什么区别?
你什么时候会用一个代替另一个?
当前回答
这说明了这一点。概要:const必须在声明时初始化,readonly可以在构造函数上初始化(因此,根据使用的构造函数,其值不同)。
编辑:关于细微的差异,请参见上面吉树的gotcha
其他回答
有一件事要补充人们上面所说的。如果程序集包含只读值(例如,只读MaxFooCount=4;),则可以通过使用不同的值(例如只读MaxFooCount=5;)发送该程序集的新版本来更改调用程序集看到的值
但如果使用常量,则在编译调用者时,它将被折叠到调用者的代码中。
如果你已经达到了C#的熟练程度,你就可以阅读比尔·瓦格纳的书《有效的C#:提高你的C语言的50种具体方法》了#它详细回答了这个问题(以及其他49个问题)。
有一个与常量的gotcha!如果从另一个程序集引用常量,则其值将直接编译到调用程序集中。这样,当您更新引用程序集中的常量时,它不会在调用程序集中发生更改!
除了
必须在常量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#-比尔·瓦格纳
常量将作为文本值编译到使用者中,而静态字符串将作为对定义值的引用。
作为练习,尝试创建一个外部库并在控制台应用程序中使用它,然后更改库中的值并重新编译它(而不重新编译用户程序),将DLL放入目录并手动运行EXE,您应该会发现常量字符串没有改变。
又一次抓住了。由于const实际上只适用于基本数据类型,如果您想使用类,您可能会感到“被迫”使用ReadOnly。然而,当心陷阱!ReadOnly表示不能用其他对象替换对象(不能使其引用其他对象)。但是任何引用对象的进程都可以自由修改对象内的值!因此,不要困惑地认为ReadOnly意味着用户无法更改内容。C#中没有简单的语法可以防止类的实例化更改其内部值(据我所知)。