C# 静态只读与常量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/755685/
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
Static readonly vs const
提问by Svish
I've read around about const
and static readonly
fields. We have some classes which contains only constant values. Used for various things around in our system. So I am wondering if my observation is correct:
我已经阅读了关于const
和static readonly
领域的信息。我们有一些只包含常量值的类。用于我们系统中的各种事物。所以我想知道我的观察是否正确:
Should these kind of constant values always be static readonly
for everything that is public? And only use const
for internal/protected/private values?
这种恒定值是否应该始终static readonly
适用于所有公开的事物?并且仅const
用于内部/受保护/私有值?
What do you recommend? Should I maybe even not use static readonly
fields, but rather use properties maybe?
你有什么建议吗?我是否应该甚至不使用static readonly
字段,而是使用属性?
采纳答案by Marc Gravell
public static readonly
fields are a little unusual; public static
properties (with only a get
) would be more common (perhaps backed by a private static readonly
field).
public static readonly
字段有点不寻常;public static
属性(只有 a get
)会更常见(可能由private static readonly
字段支持)。
const
values are burned directly into the call-site; this is double edged:
const
值被直接烧录到调用站点中;这是双刃剑:
- it is useless if the value is fetched at runtime, perhaps from config
- if you change the value of a const, you need to rebuild all the clients
- but it can be faster, as it avoids a method call...
- ...which might sometimes have been inlined by the JIT anyway
- 如果该值是在运行时获取的,可能是从配置中获取的,则它是无用的
- 如果你改变了一个 const 的值,你需要重建所有的客户端
- 但它可以更快,因为它避免了方法调用......
- ...无论如何有时可能已被 JIT 内联
If the value will neverchange, then const is fine - Zero
etc make reasonable consts ;p Other than that, static
properties are more common.
如果该值永远不会改变,那么 const 就可以了 -Zero
等等做出合理的 consts ;p 除此之外,static
属性更常见。
回答by Chris S
One thing to note is constis restricted to primitive/value types (the exception being strings)
需要注意的一件事是const仅限于原始/值类型(字符串除外)
回答by Peter
Few more relevant things to be noted:
还有一些需要注意的相关事项:
const int a
const int a
- must be initialized.
- initialization must be at compile time.
- 必须初始化。
- 初始化必须在编译时进行。
readonly int a
只读 int a
- can use a default value, without initializing.
- initialization can be done at run time(Edit: within constructor only).
- 可以使用默认值,无需初始化。
- 初始化可以在运行时完成(编辑:仅在构造函数中)。
回答by Peter Meyer
My preference is to use constwhenever I can, which as mentioned above is limited to literal expressions or something that does not require evaluation.
我的偏好是尽可能使用const,如上所述,它仅限于文字表达式或不需要评估的东西。
If I hit up against that limitation, then I fallback to static readonly, with one caveat. I would generally use a public static property with a getter and a backing private static readonlyfield as Marc mentions here.
如果我遇到了这个限制,那么我会退回到static readonly,但有一个警告。我通常会使用带有 getter 的公共静态属性和支持私有静态只读字段,正如 Marc在此处提到的那样。
回答by Michael Stum
I would use static readonly
if the Consumeris in a different assembly. Having the const
and the Consumerin two different assemblies is a nice way to shoot yourself in the foot.
static readonly
如果消费者在不同的程序集中,我会使用。将 theconst
和Consumer放在两个不同的程序集中是一种很好的打击自己的方式。
回答by yazanpro
The readonly
keyword is different from the const
keyword. A const
field can only be initialized at the declaration of the field. A readonly
field can be initialized either at the declaration or in a constructor. Therefore, readonly
fields can have different values depending on the constructor used. Also, while a const
field is a compile-time constant, the readonly
field can be used for runtime constants
所述readonly
关键字是从不同的const
关键字。一个const
字段只能在外地的声明进行初始化。一个readonly
字段可以在声明或构造函数初始化。因此,readonly
字段可以根据使用的构造函数具有不同的值。此外,虽然const
字段是编译时常量,但该readonly
字段可用于运行时常量
回答by mayank
Const:Const is nothing but "constant", a variable of which the value is constant but at compile time. And it's mandatory to assign a value to it. By default a const is static and we cannot change the value of a const variable throughout the entire program.
Static ReadOnly:A Static Readonly type variable's value can be assigned at runtime or assigned at compile time and changed at runtime. But this variable's value can only be changed in the static constructor. And cannot be changed further. It can change only once at runtime
Const:Const 只不过是“常量”,一个变量,其值是常量,但在编译时。并且必须为其分配一个值。默认情况下,const 是静态的,我们不能在整个程序中更改 const 变量的值。
静态只读:静态只读类型变量的值可以在运行时分配或在编译时分配并在运行时更改。但是这个变量的值只能在静态构造函数中改变。并且无法进一步更改。它只能在运行时更改一次
Reference: c-sharpcorner
回答by Jeppe Stig Nielsen
This is just a supplement to the other answers. I will not repeat them (now four years later).
这只是对其他答案的补充。我不会重复它们(现在四年后)。
There are situations where a const
and a non-const have different semantics. For example:
在某些情况下,aconst
和非常量具有不同的语义。例如:
const int y = 42;
static void Main()
{
short x = 42;
Console.WriteLine(x.Equals(y));
}
prints out True
, whereas:
打印出来True
,而:
static readonly int y = 42;
static void Main()
{
short x = 42;
Console.WriteLine(x.Equals(y));
}
writes False
.
写道False
。
The reason is that the method x.Equals
has two overloads, one that takes in a short
(System.Int16
) and one that takes an object
(System.Object
). Now the question is whether one or both apply with my y
argument.
原因是该方法x.Equals
有两个重载,一个接受short
( System.Int16
) 和一个接受object
( System.Object
)。现在的问题是一个或两个都适用于我的y
论点。
When y
is a compile-time constant (literal), the const
case, it becomes important that there does exist an implicit conversion fromint
toshort
provided that the int
is a constant, and provided that the C# compiler verifies that its value is within the range of a short
(which 42
is). See Implicit constant expression conversionsin the C# Language Specification. So both overloads have to be considered. The overload Equals(short)
is preferred (any short
is an object
, but not all object
are short
). So y
is converted to short
, and that overload is used. Then Equals
compares two short
of identical value, and that gives true
.
当y
是一个编译时间常数(字面),所述const
情况下,也有不存在的隐式转换变得重要从int
到short
提供的int
是一个常数,并且条件是C#编译器验证其值的范围内short
(这42
是)。请参阅C# 语言规范中的隐式常量表达式转换。所以这两种重载都必须考虑。重载Equals(short)
是首选(任何short
是object
,但不是所有object
都是short
)。Soy
转换为short
,并使用该重载。然后Equals
比较两个short
相同的值,得到true
。
When y
is not a constant, no implicitconversion from int
to short
exists. That's because in general an int
may be too huge to fit into a short
. (An explicitconversion does exist, but I didn't say Equals((short)y)
, so that's not relevant.) We see that only one overload applies, the Equals(object)
one. So y
is boxed to object
. Then Equals
is going to compare a System.Int16
to a System.Int32
, and since the run-time types do not even agree, that will yield false
.
Wheny
不是常量,不存在从to 的隐式转换。那是因为一般来说 an可能太大而无法放入. (确实存在显式转换,但我没有说,所以这不相关。)我们看到只有一个重载适用,即一个。所以被装箱到。然后将 a与 a进行比较,并且由于运行时类型甚至不一致,这将产生。int
short
int
short
Equals((short)y)
Equals(object)
y
object
Equals
System.Int16
System.Int32
false
We conclude that in some (rare) cases, changing a const
type member to a static readonly
field (or the other way, when that is possible) can change the behavior of the program.
我们得出结论,在某些(罕见)情况下,将const
类型成员更改为static readonly
字段(或其他方式,如果可能)可以更改程序的行为。
回答by Ramesh Rajendran
const
and readonly
are similar, but they are not exactly the same.
const
和readonly
是相似的,但它们并不完全相同。
A const
field is a compile-time constant, meaning that that value can be computed at compile-time. A readonly
field enables additional scenarios in which some code must be run during construction of the type. After construction, a readonly
field cannot be changed.
甲const
字段是一个编译时间常数,这意味着该值可以在编译时计算。甲readonly
字段允许在其中一些代码必须结构的类型的期间运行附加情景。施工后,readonly
不能更改字段。
For instance, const
members can be used to define members like:
例如,const
成员可用于定义成员,如:
struct Test
{
public const double Pi = 3.14;
public const int Zero = 0;
}
Since values like 3.14 and 0 are compile-time constants. However, consider the case where you define a type and want to provide some pre-fab instances of it. E.g., you might want to define a Color class and provide "constants" for common colors like Black, White, etc. It isn't possible to do this with const members, as the right hand sides are not compile-time constants. One could do this with regular static members:
因为像 3.14 和 0 这样的值是编译时常量。但是,请考虑您定义类型并希望提供它的一些预制实例的情况。例如,您可能想要定义一个 Color 类并为常用颜色(如 Black、White 等)提供“常量”。使用 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, green, blue) = (r, g, b);
}
But then there is nothing to keep a client of Color from mucking with it, perhaps by swapping the Black and White values. Needless to say, this would cause consternation for other clients of the Color class. The "readonly" feature addresses this scenario.
但是没有什么可以阻止 Color 的客户端使用它,也许是通过交换 Black 和 White 值。不用说,这会引起 Color 类的其他客户的惊愕。“只读”功能解决了这种情况。
By simply introducing the readonly
keyword in the declarations, we preserve the flexible initialization while preventing client code from mucking around.
通过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, green, blue) = (r, g, b);
}
It is interesting to note that const members are always static, whereas a readonly member can be either static or not, just like a regular field.
有趣的是,const 成员总是静态的,而 readonly 成员可以是静态的,也可以不是,就像常规字段一样。
It is possible to use a single keyword for these two purposes, but this leads to either versioning problems or performance problems. Assume for a moment that we used a single keyword for this (const) and a developer wrote:
可以将单个关键字用于这两个目的,但这会导致版本问题或性能问题。假设我们为此(const)使用了一个关键字,并且开发人员写道:
public class A
{
public static const C = 0;
}
and a different developer wrote code that relied on A:
另一个开发人员编写了依赖于 A 的代码:
public class B
{
static void Main() => Console.WriteLine(A.C);
}
Now, can the code that is generated rely on the fact that A.C is a compile-time constant? I.e., can the use of A.C simply be replaced by the value 0? If you say "yes" to this, then that means that the developer of A cannot change the way that A.C is initialized -- this ties the hands of the developer of A without permission.
现在,生成的代码能否依赖于 AC 是编译时常量这一事实?即,AC 的使用可以简单地替换为值 0 吗?如果你对此说“是”,那么这意味着 A 的开发者不能改变 AC 的初始化方式——这在未经许可的情况下束缚了 A 的开发者的手。
If you say "no" to this question then an important optimization is missed. Perhaps the author of A is positive that A.C will always be zero. The use of both const and readonly allows the developer of A to specify the intent. This makes for better versioning behavior and also better performance.
如果你对这个问题说“不”,那么就错过了一个重要的优化。也许 A 的作者肯定 AC 永远为零。const 和 readonly 的使用允许 A 的开发人员指定意图。这有助于实现更好的版本控制行为和更好的性能。
回答by dasumohan89
const:
常量:
- value should be given upon declaration
- compile time constant
- 值应在声明时给出
- 编译时间常数
readonly:
只读:
- value can be given upon declaration or during runtime using constructors.The value may vary depend upon the constructor used.
- run time constant
- 值可以在声明时或在运行时使用构造函数给出。该值可能因所使用的构造函数而异。
- 运行时间常数