const
C#和C#有什么区别readonly
?
您什么时候会使用其中一种?
除了明显的区别
const
VSreadonly
值时声明值可以动态计算,但需要在构造函数退出之前分配......之后它被冻结。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
's IL。这意味着如果明天我更新I_CONST_VALUE
到 20,AssemblyB
在我重新编译之前仍然会有 2。readonly
值的情况下,它就像ref
一个内存位置。该值未烘焙到AssemblyB
的 IL 中。这意味着如果内存位置被更新,AssemblyB
则无需重新编译即可获取新值。所以如果I_RO_VALUE
更新到30,只需要build AssemblyA
,不需要重新编译所有客户端。因此,如果您确信常量的值不会改变,请使用const
.
public const int CM_IN_A_METER = 100;
但是,如果您有一个可能会改变的常数(例如精度).. 或者有疑问时,请使用readonly
.
public readonly float PI = 3.14;
更新:Aku 需要提及,因为他首先指出了这一点。我还需要插入我学到的地方:Effective C# - Bill Wagner
const 有一个陷阱!如果您从另一个程序集中引用一个常量,它的值将直接编译到调用程序集中。这样,当您更新引用程序集中的常量时,它不会在调用程序集中更改!
只是要补充一点,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
: 这个值只能在构造函数中改变。在正常功能中无法更改。
常量成员是在编译时定义的,不能在运行时更改。常量使用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
(它们是隐式静态的)只读
只读有一个小问题。可以在构造函数中多次设置只读字段。即使该值是在两个不同的链式构造函数中设置的,它仍然是允许的。
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 如何不是版本安全的,或者与引用类型相关。
摘要:
只读:可以在运行时通过 Tor 更改值。但不是通过成员函数
常量:默认为静态。值不能从任何地方更改(Ctor、Function、运行时等无处)
还有一个问题:只读值可以通过反射被“狡猾”的代码改变。
var fi = this.GetType()
.BaseType
.GetField("_someField",
BindingFlags.Instance | BindingFlags.NonPublic);
fi.SetValue(this, 1);
我相信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 字段是静态的,但反之则不正确。
何时使用const
或readonly
const
readonly
App.config
,但一旦初始化就无法更改标记为 const 的变量只不过是强类型的 #define 宏,在编译时 const 变量引用被内联文字值替换。因此,只能以这种方式使用某些内置的原始值类型。标记为只读的变量可以在运行时在构造函数中设置,并且它们的只读性也在运行时强制执行。有一些与此相关的较小的性能成本,但这意味着您可以将 readonly 用于任何类型(甚至是引用类型)。
此外,const 变量本质上是静态的,而 readonly 变量可以是特定于实例的,如果需要的话。
C#.Net 中的 const 和 readonly 字段之间存在显着差异
const 默认是静态的,需要用常量值初始化,以后不能修改。构造函数中也不允许更改值。它不能用于所有数据类型。对于前日期时间。它不能与 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
readonly 可以声明为静态的,但不是必需的。声明时无需初始化。可以使用构造函数分配或更改其值。因此,它在用作实例类成员时具有优势。两个不同的实例化可能具有不同的只读字段值。对于前 -
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。使用 const 是不可能的。
另一个问题。
由于 const 实际上只适用于基本数据类型,如果你想使用一个类,你可能会觉得“被迫”使用 ReadOnly。但是,当心陷阱!ReadOnly 意味着你不能用另一个对象替换这个对象(你不能让它引用另一个对象)。但是任何引用对象的进程都可以自由修改对象内部的值!
所以不要误以为 ReadOnly 意味着用户不能改变事情。C# 中没有简单的语法来防止类的实例化更改其内部值(据我所知)。
Aconst
必须是硬编码的,其中 asreadonly
可以在类的构造函数中设置。
常量将作为文字值编译到使用者中,而静态字符串将用作对所定义值的引用。
作为练习,尝试创建一个外部库并在控制台应用程序中使用它,然后更改库中的值并重新编译它(无需重新编译消费者程序),将 DLL 放入目录并手动运行 EXE,您应该会发现常量字符串不会改变。
const 和 readonly 相似,但并不完全相同。const 字段是编译时常量,这意味着可以在编译时计算该值。只读字段允许在构造类型期间必须运行某些代码的其他场景。构造后,只读字段无法更改。
例如, const 成员可用于定义成员,例如:
struct Test
{
public const double Pi = 3.14;
public const int Zero = 0;
}
因为像 3.14 和 0 这样的值是编译时常量。但是,请考虑您定义类型并希望提供一些预制实例的情况。例如,您可能想要定义一个 Color 类并为黑色、白色等常见颜色提供“常量”。使用 const 成员是不可能的,因为右侧不是编译时常量。可以使用常规静态成员执行此操作:
public class Color
{
public static Color Black = new Color(0, 0, 0);
public static Color White = new Color(255, 255, 255);
public static Color Red = new Color(255, 0, 0);
public static Color Green = new Color(0, 255, 0);
public static Color Blue = new Color(0, 0, 255);
private byte red, green, blue;
public Color(byte r, byte g, byte b) {
red = r;
green = g;
blue = b;
}
}
但是没有什么可以阻止 Color 的客户使用它,也许是通过交换 Black 和 White 值。不用说,这会引起 Color 类的其他客户的恐慌。“只读”功能解决了这种情况。通过在声明中简单地引入 readonly 关键字,我们保留了灵活的初始化,同时防止客户端代码乱七八糟。
public class Color
{
public static readonly Color Black = new Color(0, 0, 0);
public static readonly Color White = new Color(255, 255, 255);
public static readonly Color Red = new Color(255, 0, 0);
public static readonly Color Green = new Color(0, 255, 0);
public static readonly Color Blue = new Color(0, 0, 255);
private byte red, green, blue;
public Color(byte r, byte g, byte b) {
red = r;
green = g;
blue = b;
}
}
有趣的是,const 成员始终是静态的,而 readonly 成员可以是静态的,也可以不是静态的,就像常规字段一样。
可以为这两个目的使用单个关键字,但这会导致版本控制问题或性能问题。假设我们为此使用了一个关键字(const)并且开发人员写道:
public class A
{
public static const C = 0;
}
另一个开发人员编写了依赖于 A 的代码:
public class B
{
static void Main() {
Console.WriteLine(A.C);
}
}
现在,生成的代码可以依赖于 AC 是编译时常量这一事实吗?即,AC 的使用可以简单地用值 0 代替吗?如果您对此说“是”,那么这意味着 A 的开发人员无法更改 AC 的初始化方式——这在未经许可的情况下束缚了 A 的开发人员的手。如果你对这个问题说“不”,那么就会错过一个重要的优化。也许 A 的作者肯定 AC 将永远为零。const 和 readonly 的使用允许 A 的开发人员指定意图。这有助于更好的版本控制行为和更好的性能。
ReadOnly :该值只会从类的构造函数中初始化一次。
const:可以在任何函数中初始化,但只能初始化一次
不同之处在于静态只读字段的值是在运行时设置的,因此对于程序的不同执行,它可以具有不同的值。但是,const 字段的值设置为编译时常量。
请记住:对于引用类型,在两种情况下(静态和实例),只读修饰符只会阻止您为该字段分配新引用。它特别不会使引用指向的对象不可变。
有关详细信息,请参阅有关此主题的 C# 常见问题解答:http: //blogs.msdn.com/csharpfaq/archive/2004/12/03/274791.aspx
常量变量在编译时声明和初始化。病房后无法更改该值。只读变量将仅从类的静态构造函数初始化。仅当我们要在运行时分配值时才使用只读。
原则上; 您可以在运行时将静态只读字段的值分配给非常量值,而必须为 const 分配一个常量值。
对人们上面所说的内容要补充一件事。如果您有一个包含只读值的程序集(例如只读 MaxFooCount = 4; ),您可以通过发送具有不同值的新版本的程序集(例如只读 MaxFooCount = 5;)来更改调用程序集看到的值
但是使用 const 时,它会在调用者编译时被折叠到调用者的代码中。
如果您已达到此 C# 熟练程度,您就可以阅读 Bill Wagner 的书《有效的 C#:50 种改进 C# 的具体方法》,它详细回答了这个问题(以及其他 49 件事)。
主要区别在于Const 是#DEFINE 的C 等价物。该数字实际上被替换为 a-la 预编译器。Readonly 实际上被视为一个变量。
当您的项目 A 依赖于项目 B 中的公共常量时,这种区别尤其相关。假设公共常量发生了变化。现在您选择的 const/readonly 将影响项目 A 的行为:
const:项目 A 没有捕获新值(当然,除非它用新的 const 重新编译),因为它是用替换的常量编译的。
只读:项目 A 将始终向项目 B 询问其变量值,因此它将获取 B 中公共常量的新值。
老实说,我建议您对几乎所有内容都使用只读,除了真正的通用常量(例如 Pi、Inches_To_Centimeters)。对于任何可能改变的东西,我说使用只读。
希望这会有所帮助,艾伦。
Const:应用程序生命周期内的绝对常数值。
Readonly:可以在运行时更改。
readonly 字段的值可以更改。但是, const 字段的值不能更改。
在只读字段中,我们可以在声明时或在该类的构造函数中赋值。如果是常量,我们只能在声明时赋值。
Readonly 可以与 Static 修饰符一起使用,但常量不能与 static 一起使用。