是什么区别const
,并readonly
和你使用一个比其他?
除了明显的差异
必须声明const
VS 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
值的情况下,它就像一个find-replace,值2被'烘焙'到AssemblyB
'IL'.这意味着如果明天我将来会更新I_CONST_VALUE
到20.AssemblyB
直到我重新编译它仍然会有2.
在readonly
值的情况下,它就像ref
一个内存位置.该值未被烘焙到AssemblyB
IL中.这意味着如果更新内存位置,则AssemblyB
获取新值而不重新编译.所以如果I_RO_VALUE
更新到30,你只需要构建AssemblyA
.所有客户端都不需要重新编译.
因此,如果您确信常量的值不会改变,请使用a const
.
public const int CM_IN_A_METER = 100;
但是如果你有一个可能改变的常数(例如,精确度)......或者当有疑问时,使用a readonly
.
public readonly float PI = 3.14;
更新:Aku需要提一下因为他首先指出了这一点.另外我需要插上我学到的东西.. 有效的C# - 比尔瓦格纳
有一个充满争议的问题!如果从另一个程序集引用常量,则其值将被编译到调用程序集中.这样,当您更新引用的程序集中的常量时,它将不会在调用程序集中更改!
常量默认为静态
它们必须在编译时有一个值(你可以有例如3.14*2,但不能调用方法)
可以在函数内声明
被复制到使用它们的每个程序集中(每个程序集都获取值的本地副本)
可以在属性中使用
必须具有设置值,在构造函数退出时
在创建实例时进行评估
在代码执行遇到类引用时(在创建新实例或执行静态方法时)进行评估
在静态构造函数完成时必须具有计算值
不建议将ThreadStaticAttribute放在这些上(静态构造函数将仅在一个线程中执行,并将为其线程设置值;所有其他线程将使此值未初始化)
只是要添加,ReadOnly用于引用类型只使引用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 } }
这解释了它.总结:const必须在声明时初始化,readonly可以在构造函数上初始化(因此根据使用的构造函数具有不同的值).
编辑:看到Gishu的上面的细微差别
const
:任何地方都无法改变.
readonly
:此值只能在构造函数中更改.在正常功能中无法更改.
有一个小的陷阱与readonly.可以在构造函数中多次设置只读字段.即使该值在两个不同的链式构造函数中设置,它仍然是允许的.
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
关键字声明为字段,必须在声明时初始化.
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; } }
常量
它们不能被声明为static
(它们是隐式静态的)
在编译时评估constant的值
常量仅在声明时初始化
只读
它们可以是实例级也可以是静态的
该值在运行时计算
readonly可以在声明中或在构造函数中的代码中初始化
const是一个编译时常量,而readonly允许在运行时计算一个值,并在构造函数或字段初始化程序中设置.因此,'const'始终是常量,但'readonly'只有在分配后才是只读的.
C#团队的Eric Lippert提供了有关不同类型的不变性的更多信息
这是另一个链接,演示了const不是版本安全的,或者与引用类型相关.
摘要:
const属性的值在编译时设置,不能在运行时更改
Const不能被标记为静态 - 关键字表示它们是静态的,不像readonly字段那样.
除了值(原始)类型之外,Const不能是任何东西
readonly关键字将该字段标记为不可更改.但是,可以在类的构造函数内更改属性
readonly only关键字也可以与static结合使其以与const(表面上至少)相同的方式运行.当你看两者之间的IL时,有一个显着的差异
const字段在IL中标记为"literal",而readonly是"initonly"
只读:可以在运行时通过Ctor更改值.但不是通过成员函数
常数:通过defult静态.价值无法从任何地方改变(Ctor,Function,runtime等no-where)
还有另一个问题:readonly值可以通过反射的"狡猾"代码来改变.
var fi = this.GetType() .BaseType .GetField("_someField", BindingFlags.Instance | BindingFlags.NonPublic); fi.SetValue(this, 1);
我可以使用反射更改C#中的私有只读继承字段吗?
我相信const
所有对象的值都是相同的(并且必须用文字表达式初始化),而readonly
每个实例可以有所不同......
它们都是常量,但在编译时也可以使用const.这意味着区别的一个方面是您可以使用const变量作为属性构造函数的输入,而不是只读变量.
例:
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; } } }
我们办公室的一名团队成员就何时使用const,static和readonly提供了以下指导:
当你有一个你可以在运行时知道的类型的变量(字符串文字,整数,双数,枚举......)时,你希望使用const,你希望类的所有实例或消费者都能访问值不应该改变的地方.
当您拥有希望类的所有实例或使用者可以访问值可以更改的位置的数据时,请使用static.
当您拥有一个在运行时无法知道的类型变量(对象)时,请使用静态只读,您希望类的所有实例或使用者都可以访问值不应更改的位置.
当您拥有一个实例级变量时,只要使用readonly,您将在创建对象时知道该变量不应该更改.
最后要注意的是:const字段是静态的,但反之则不然.