C#中的const和readonly有什么区别?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/55984/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 10:10:10  来源:igfitidea点击:

What is the difference between const and readonly in C#?

提问by Readonly

What is the difference between constand readonlyin C#?

在 C# 中constreadonly在 C# 中有什么区别?

When would you use one over the other?

你什么时候会使用一个?

采纳答案by Gishu

Apart from the apparent difference of

除了明显的区别

  • having to declare the value at the time of a definition for a constVS readonlyvalues can be computed dynamically but need to be assigned before the constructor exits.. after that it is frozen.
  • 'const's are implicitly static. You use a ClassName.ConstantNamenotation to access them.
  • 必须在定义constVSreadonly值时声明值可以动态计算,但需要在构造函数退出之前分配..之后它被冻结。
  • 'const' 是隐含的static。您可以使用ClassName.ConstantName符号来访问它们。

There is a subtle difference. Consider a class defined in AssemblyA.

有一个微妙的区别。考虑定义在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;
  }
}

AssemblyBreferences AssemblyAand uses these values in code. When this is compiled,

AssemblyBAssemblyA在代码中引用并使用这些值。当这个编译时,

  • in the case of the constvalue, it is like a find-replace, the value 2 is 'baked into' the AssemblyB's IL. This means that if tomorrow I'll update I_CONST_VALUEto 20 in the future. AssemblyBwould still have 2 till I recompile it.
  • in the case of the readonlyvalue, it is like a refto a memory location. The value is not baked into AssemblyB's IL. This means that if the memory location is updated, AssemblyBgets the new value without recompilation. So if I_RO_VALUEis updated to 30, you only need to build AssemblyA. All clients do not need to be recompiled.
  • const值的情况下,它就像一个查找替换,值 2 被“烘焙”到AssemblyB的 IL 中。这意味着如果明天我将I_CONST_VALUE在未来更新到 20。AssemblyB在我重新编译它之前仍然会有 2 个
  • readonly值的情况下,它就像ref一个内存位置。该值不包含AssemblyB在 的 IL 中。这意味着如果内存位置被更新,AssemblyB则无需重新编译即可获得新值。所以如果I_RO_VALUE更新到 30,你只需要构建AssemblyA. 不需要重新编译所有客户端。

So if you are confident that the value of the constant won't change use a const.

因此,如果您确信常量的值不会改变,请使用const.

public const int CM_IN_A_METER = 100;

But if you have a constant that may change (e.g. w.r.t. precision).. or when in doubt, use a readonly.

但是,如果您有一个可能会改变的常量(例如wrt 精度)...或者有疑问时,请使用readonly.

public readonly float PI = 3.14;

Update: Aku needs to get a mention coz he pointed this out first. Also I need to plug where I learned this.. Effective C# - Bill Wagner

更新:Aku 需要得到提及,因为他首先指出了这一点。我还需要插入我学到的地方..有效的 C# - Bill Wagner

回答by Daren Thomas

I believe a constvalue is the same for all objects (and must be initialized with a literal expression), whereas readonlycan be different for each instantiation...

我相信const所有对象的值都是相同的(并且必须用文字表达式初始化),而readonly每个实例化都可以不同......

回答by Vinko Vrsalovic

This explains it. Summary: const must be initialized at declaration time, readonly can be initialized on the constructor (and thus have a different value depending on the constructor used).

这就解释了。总结:const 必须在声明时初始化,readonly 可以在构造函数上初始化(因此根据使用的构造函数有不同的值)。

EDIT: See Gishu's gotcha above for the subtle difference

编辑:请参阅上面的 Gishu's gotcha 以了解细微差别

回答by Wheelie

A const is a compile-time constant whereas readonly allows a value to be calculated at run-time and set in the constructor or field initializer. So, a 'const' is always constant but 'readonly' is read-only once it is assigned.

const 是编译时常量,而 readonly 允许在运行时计算值并在构造函数或字段初始值设定项中设置。因此,'const' 始终是常量,但 'readonly' 一旦被分配就为只读。

Eric Lippertof the C# team has more information on different types of immutability

C# 团队的Eric Lippert有更多关于不同类型不变性的信息

回答by aku

There is a gotcha with consts! If you reference a constant from another assembly, its value will be compiled right into the calling assembly. That way when you update the constant in the referenced assembly it won't change in the calling assembly!

consts 有一个问题!如果您从另一个程序集中引用一个常量,它的值将被直接编译到调用程序集中。这样,当您更新引用程序集中的常量时,它不会在调用程序集中更改!

回答by Wedge

Variables marked const are little more than strongly typed #define macros, at compile time const variable references are replaced with inline literal values. As a consequence only certain built-in primitive value types can be used in this way. Variables marked readonly can be set, in a constructor, at run-time and their read-only-ness is enforced during run-time as well. There is some minor performance cost associated with this but it means you can use readonly with any type (even reference types).

标记为 const 的变量只不过是强类型的 #define 宏,在编译时 const 变量引用被内联文字值替换。因此,只能以这种方式使用某些内置的原始值类型。标记为只读的变量可以在构造函数中在运行时设置,并且它们的只读性也在运行时强制执行。有一些与此相关的较小性能成本,但这意味着您可以对任何类型(甚至引用类型)使用 readonly。

Also, const variables are inherently static, whereas readonly variables can be instance specific if desired.

此外,const 变量本质上是静态的,而 readonly 变量可以是特定于实例的(如果需要)。

回答by Wedge

Just to add, ReadOnly for reference types only makes the reference readonly not the values. For example:

只是补充一点,引用类型的 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
  }
}

回答by Anthony

One thing to add to what people have said above. If you have an assembly containing a readonly value (e.g. readonly MaxFooCount = 4; ), you can change the value that calling assemblies see by shipping a new version of that assembly with a different value (e.g. readonly MaxFooCount = 5;)

一件事要补充上面人们所说的。如果您的程序集包含只读值(例如 readonly MaxFooCount = 4; ),您可以通过发布具有不同值的该程序集的新版本(例如 readonly MaxFooCount = 5;)来更改调用程序集看到的值

But with a const, it would be folded into the caller's code when the caller was compiled.

但是对于const,它会在调用者编译时被折叠到调用者的代码中。

If you've reached this level of C# proficiency, you are ready for Bill Wagner's book, Effective C#: 50 Specific Ways to Improve Your C# Which answers this question in detail, (and 49 other things).

如果您已经达到了 C# 熟练程度,那么您已经准备好阅读 Bill Wagner 的书《Effective C#: 50 Specific Ways to Improvement Your C#》,该书详细回答了这个问题(以及其他 49 件事)。

回答by AlanR

The key difference is that Const is the C equivalent of #DEFINE. The number literally gets substituted a-la precompiler. Readonly is actually treated as a variable.

关键的区别在于,Const 是#DEFINE 的 C 等价物。该数字实际上被替换为 a-la 预编译器。Readonly 实际上被视为一个变量。

This distinction is especially relevant when you have Project A depending on a Public constant from Project B. Suppose the public constant changes. Now your choice of const/readonly will impact the behavior on project A:

当您的项目 A 依赖于项目 B 的公共常量时,这种区别尤其重要。假设公共常量发生变化。现在您对 const/readonly 的选择将影响项目 A 的行为:

Const: project A does not catch the new value (unless it is recompiled with the new const, of course) because it was compiled with the constants subtituted in.

Const:项目 A 没有捕获新值(当然,除非它用新的 const 重新编译),因为它是用替换的常量编译的。

ReadOnly: Project A will always ask project B for it's variable value, so it will pick up the new value of the public constant in B.

只读:项目 A 将始终向项目 B 询问它的变量值,因此它将获取 B 中公共常量的新值。

Honestly, I would recommend you use readonly for nearly everything except truly universal constants ( e.g. Pi, Inches_To_Centimeters). For anything that could possibly change, I say use readonly.

老实说,除了真正的通用常量(例如 Pi、Inches_To_Centimeters)之外,我建议您对几乎所有内容都使用 readonly。对于任何可能改变的东西,我说使用只读。

Hope this helps, Alan.

希望这会有所帮助,艾伦。

回答by Hallgrim

They are both constant, but a const is available also at compile time. This means that one aspect of the difference is that you can use const variables as input to attribute constructors, but not readonly variables.

它们都是常量,但在编译时也可以使用常量。这意味着差异的一方面是您可以使用 const 变量作为属性构造函数的输入,但不能使用只读变量。

Example:

例子:

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; }
  }
}