const
和 readonly
在 C# 中有什么区别?
在什么情况下会使用其中一个而不是另一个?
除了明显的区别外
const
必须在定义时声明值,而 readonly
值可以动态计算,但需要在构造函数退出之前分配。之后它就会被冻结。const
是隐式的 static
。您可以使用 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
并在代码中使用这些值。当编译时:const
值,它就像查找和替换一样。值2被“固化”在AssemblyB
的IL中。这意味着如果明天我将I_CONST_VALUE
更新为20,则AssemblyB
仍然具有2,直到重新编译它。readonly
值,它就像是对内存位置的ref
。该值不会固化在AssemblyB
的IL中。这意味着如果更改了内存位置,AssemblyB
会获得新值而无需重新编译。因此,如果将I_RO_VALUE
更新为30,则只需要构建AssemblyA
,所有客户端都不需要重新编译。const
。public const int CM_IN_A_METER = 100;
但如果你有一个可能会改变的常量(例如与精度相关),或者不确定时,请使用readonly
。
public readonly float PI = 3.14;
更新:Aku需要得到提及,因为他首先指出了这一点。此外,我需要推荐我学习这个的地方:Effective C# - Bill Wagner
readonly
变量是指一旦构造函数完成后就不允许再被改变,即使通过反射也不行。虽然运行时没有强制执行这个规则,但是也不应该认为这样就可以修改 string.Empty
为 "Hello, world!"
,或者认为代码不需要假定 string.Empty
总是一个空字符串。 - user743382常量有一个陷阱!如果你从另一个程序集中引用一个常量,它的值将被编译到调用程序集中。这样当你在被引用的程序集中更新常量时,它在调用程序集中不会改变!
readonly
只会使得引用本身变为只读,而不是其中的值。例如:public class Const_V_Readonly
{
public const int I_CONST_VALUE = 2;
public readonly char[] I_RO_VALUE = new Char[]{'a', 'b', 'c'};
public UpdateReadonly()
{
I_RO_VALUE[0] = 'V'; //perfectly legal and will update the value
I_RO_VALUE = new char[]{'V'}; //will cause compiler error
}
}
string
这种类型,您还可以使用哪些引用类型作为常量? - springy76const
:无法在任何地方更改。
readonly
:此值只能在构造函数中更改。不能在普通函数中更改。
这里有解释。总结:常量必须在声明时进行初始化,只读字段可以在构造函数中初始化(因此根据使用的构造函数而有不同的值)。
编辑:请参阅Gishu的陷阱以了解微妙差别。
常量成员在编译时定义并且无法在运行时更改。使用const
关键字将常量声明为字段,并且必须在声明时进行初始化。
public class MyClass
{
public const double PI1 = 3.14159;
}
readonly
成员变量类似于常量,它代表一个不可变的值。不同之处在于,readonly
成员变量可以在运行时,在构造函数中初始化,并且也可以像声明时一样被初始化。
public class MyClass1
{
public readonly double PI2 = 3.14159;
//or
public readonly double PI3;
public MyClass2()
{
PI3 = 3.14159;
}
}
const
static
(它们会隐式地成为静态的)readonly
static const int i = 0;
”,请明确说明。 - nawfalconst
吗? - Minh Tranreadonly有一个小问题。在构造函数中,可以多次设置只读字段的值。即使这个值在两个不同的链接构造函数中设置,它仍然是被允许的。
public class Sample {
private readonly string ro;
public Sample() {
ro = "set";
}
public Sample(string value) : this() {
ro = value; // this works even though it was set in the no-arg ctor
}
}
const是编译时常量,而readonly允许在运行时计算一个值并在构造函数或字段初始化器中设置。因此,'const'始终保持不变,但'readonly'一旦被赋值就是只读的。
C#团队的Eric Lippert在这里提供了有关不同类型的不可变性的更多信息。
这里有另一个链接展示了const在版本安全性方面不具备优势,也与引用类型无关。
总结: