在C#中常量和只读之间有什么区别?
你什么时候会用一个代替另一个?
在C#中常量和只读之间有什么区别?
你什么时候会用一个代替另一个?
当前回答
它们都是常量,但在编译时也可以使用常量。这意味着差异的一个方面是,可以使用常量变量作为属性构造函数的输入,但不能使用只读变量。
例子:
public static class Text {
public const string ConstDescription = "This can be used.";
public readonly static string ReadonlyDescription = "Cannot be used.";
}
public class Foo
{
[Description(Text.ConstDescription)]
public int BarThatBuilds {
{ get; set; }
}
[Description(Text.ReadOnlyDescription)]
public int BarThatDoesNotBuild {
{ get; set; }
}
}
其他回答
另外,只读引用类型只会使引用只读,而不会使值只读。例如:
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
}
}
常量将作为文本值编译到使用者中,而静态字符串将作为对定义值的引用。
作为练习,尝试创建一个外部库并在控制台应用程序中使用它,然后更改库中的值并重新编译它(而不重新编译用户程序),将DLL放入目录并手动运行EXE,您应该会发现常量字符串没有改变。
C#.Net中常量字段和只读字段之间存在显著差异
const在默认情况下是静态的,需要用常量值初始化,以后不能修改。构造函数中也不允许更改值。它不能与所有数据类型一起使用。对于ex-DateTime。它不能与DateTime数据类型一起使用。
public const DateTime dt = DateTime.Today; //throws compilation error
public const string Name = string.Empty; //throws compilation error
public readonly string Name = string.Empty; //No error, legal
只读可以声明为静态,但不是必需的。无需在声明时进行初始化。它的值可以使用构造函数赋值或更改。因此,它在用作实例类成员时具有优势。两个不同的实例化可能具有不同的只读字段值。对于ex-
class A
{
public readonly int Id;
public A(int i)
{
Id = i;
}
}
然后,只读字段可以用即时特定值初始化,如下所示:
A objOne = new A(5);
A objTwo = new A(10);
这里,实例objOne的只读字段值为5,objTwo的值为10。这不可能使用常量。
只读字段的值可以更改。但是,常量字段的值不能更改。
在只读字段中,我们可以在声明时或在该类的构造函数中赋值。如果是常量,我们只能在声明时赋值。
只读可以与静态修饰符一起使用,但常量不能与静态一起使用。
除了
必须在常量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#-比尔·瓦格纳