“静态只读” 与 'const'
我已经阅读了有关 const
和 static readonly
字段的内容。 我们有一些只包含常量值的类。 它们用于我们系统中的各种事物。 所以我想知道我的观察是否正确:
对于所有公开的内容,这些常量值是否应该始终是静态只读的? 并且仅将 const
用于 internal
/protected
/private
值?
你有什么建议吗? 我是否应该不使用 static readonly
字段,而是使用属性?
I've read around about const
and static readonly
fields. We have some classes which contain only constant values. They are used for various things around in our system. So I am wondering if my observation is correct:
Should these kind of constant values always be static readonly
for everything that is public? And only use const
for internal
/protected
/private
values?
What do you recommend? Should I maybe even not use static readonly
fields, but rather use properties maybe?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(22)
如果消费者位于不同的程序集中,我将使用静态只读。 将
const
和 Consumer 放在两个不同的程序集中是搬起石头砸自己的脚。I would use
static readonly
if the Consumer is in a different assembly. Having theconst
and the Consumer in two different assemblies is a nice way to shoot yourself in the foot.需要注意的一些相关事项:
const int a
readonly int a
A few more relevant things to be noted:
const int a
readonly int a
这只是对其他答案的补充。 我不会重复它们(四年后的现在)。
在某些情况下,const 和非常量具有不同的语义。 例如:
打印出
True
,而:写入
False
。原因是方法
x.Equals
有两个重载,一个重载采用short
(System.Int16
),另一种重载采用object
(object
) >系统.对象)。 现在的问题是其中之一或两者是否适用于我的y
参数。当
y
是编译时常量(文字)时,即const
情况,确实存在从的隐式转换就变得很重要>int
toshort
前提是int
是常量,并且 C# 编译器验证其值是否在short
的范围(42
是)。 请参阅 C# 语言规范中的隐式常量表达式转换。 因此必须考虑这两种过载。 首选重载Equals(short)
(任何short
都是object
,但并非所有object
都是>短
)。 因此,y
被转换为short
,并使用该重载。 然后,Equals
比较两个相同值的short
,结果为true
。当
y
不是常量时,不存在从int
到short
的隐式转换。 这是因为通常int
可能太大而无法放入short
中。 (显式转换确实存在,但我没有说Equals((short)y)
,所以这不相关。)我们看到只有一个重载适用,即等于(对象)
一。 因此,y
被装箱到object
。 然后,Equals
将比较System.Int16
和System.Int32
,并且由于运行时类型甚至不一致,因此将产生false
。我们得出的结论是,在某些(罕见)情况下,将
const
类型成员更改为static readonly
字段(或其他方式,如果可能的话)可以改变该程序。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:prints out
True
, whereas:writes
False
.The reason is that the method
x.Equals
has two overloads, one that takes in ashort
(System.Int16
) and one that takes anobject
(System.Object
). Now the question is whether one or both apply with myy
argument.When
y
is a compile-time constant (literal), theconst
case, it becomes important that there does exist an implicit conversion fromint
toshort
provided that theint
is a constant, and provided that the C# compiler verifies that its value is within the range of ashort
(which42
is). See Implicit constant expression conversions in the C# Language Specification. So both overloads have to be considered. The overloadEquals(short)
is preferred (anyshort
is anobject
, but not allobject
areshort
). Soy
is converted toshort
, and that overload is used. ThenEquals
compares twoshort
of identical value, and that givestrue
.When
y
is not a constant, no implicit conversion fromint
toshort
exists. That's because in general anint
may be too huge to fit into ashort
. (An explicit conversion does exist, but I didn't sayEquals((short)y)
, so that's not relevant.) We see that only one overload applies, theEquals(object)
one. Soy
is boxed toobject
. ThenEquals
is going to compare aSystem.Int16
to aSystem.Int32
, and since the run-time types do not even agree, that will yieldfalse
.We conclude that in some (rare) cases, changing a
const
type member to astatic readonly
field (or the other way, when that is possible) can change the behavior of the program.需要注意的一件事是 const 仅限于基元/值类型(字符串除外)。
One thing to note is const is restricted to primitive/value types (the exception being strings).
静态只读:
可以在运行时通过
静态
构造函数更改该值。 但不是通过成员函数。常量:
默认情况下
静态
。 值不能从任何地方(构造函数、函数、运行时等,任何地方)更改。只读:
可以在运行时通过构造函数更改该值。 但不是通过成员函数。
您可以查看我的存储库:C# 属性类型。
Static Read Only:
The value can be changed through a
static
constructor at runtime. But not through a member function.Constant:
By default
static
. A value cannot be changed from anywhere (constructor, function, runtime, etc. nowhere).Read Only:
The value can be changed through a constructor at runtime. But not through a member function.
You can have a look at my repository: C# property types.
来自 这个简短而清晰的 MSDN 参考。
From this short and clear MSDN reference.
const
和readonly
类似,但并不完全相同。const 字段是编译时常量,这意味着可以在编译时计算该值。 readonly 字段支持在类型构造期间必须运行某些代码的其他场景。 构建后,
readonly
字段无法更改。例如,
const
成员可用于定义如下成员:因为像 3.14 和 0 这样的值是编译时常量。 但是,请考虑您定义类型并希望提供它的一些预制实例的情况。 例如,您可能想要定义一个 Color 类并为黑色、白色等常见颜色提供“常量”。使用 const 成员不可能做到这一点,因为右侧不是编译时常量。 人们可以使用常规静态成员来做到这一点:
但是没有什么可以阻止颜色客户对其进行破坏,也许可以通过交换黑色和白色值。 不用说,这会让 Color 类的其他客户感到惊愕。 “只读”功能解决了这种情况。
通过简单地在声明中引入 readonly 关键字,我们可以保留灵活的初始化,同时防止客户端代码乱七八糟。
有趣的是,const 成员始终是静态的,而只读成员可以是静态的,也可以不是静态的,就像常规字段一样。
可以使用单个关键字来实现这两个目的,但这会导致版本控制问题或性能问题。 假设我们为此使用了单个关键字(const),并且一位开发人员写道:
另一位开发人员编写了依赖于 A 的代码:
现在,生成的代码是否可以依赖于 AC 是编译时的事实持续的? 即,AC的使用可以简单地用值0代替吗? 如果你对此说“是”,那么这意味着A的开发者不能改变AC的初始化方式——这在未经许可的情况下束缚了A的开发者的手脚。
如果您对这个问题说“不”,那么就会错过一个重要的优化。 也许 A 的作者肯定 AC 永远为零。 const 和 readonly 的使用允许 A 的开发人员指定意图。 这可以实现更好的版本控制行为和更好的性能。
const
andreadonly
are similar, but they are not exactly the same.A
const
field is a compile-time constant, meaning that that value can be computed at compile-time. Areadonly
field enables additional scenarios in which some code must be run during construction of the type. After construction, areadonly
field cannot be changed.For instance,
const
members can be used to define members like: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:
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.
By simply introducing the
readonly
keyword in the declarations, we preserve the flexible initialization while preventing client code from mucking around.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.
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:
and a different developer wrote code that relied on A:
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.
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.
我的偏好是尽可能使用 const ,正如前面的答案中提到的,它仅限于文字表达式或不需要评估的东西。
如果我遇到了这个限制,那么我会回退到静态只读,但有一个警告。 我通常会使用带有 getter 和支持 private static readonly 字段的公共静态属性,正如 Marc 提到的 这里。
My preference is to use const whenever I can, which, as mentioned in previous answers, is limited to literal expressions or something that does not require evaluation.
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 readonly field as Marc mentions here.
Const:常量变量值必须与声明一起定义,之后就不会改变。const 是隐式静态的,因此无需创建类实例我们就可以访问它们。 strong> 这在编译时有价值。
ReadOnly:我们可以在声明时定义只读变量值,也可以在运行时使用构造函数。 如果没有类实例,则无法访问只读变量。
静态只读:我们可以在声明时定义静态只读变量值,也可以仅通过静态构造函数来定义,但不能使用任何其他构造函数。 我们还可以在不创建类实例的情况下访问这些变量(作为静态变量)。
如果我们必须使用不同程序集中的变量,静态只读将是更好的选择。 请查看以下博客文章中的完整详细信息:
Const Strings – 一种非常方便的搬起石头砸自己脚的方法
Const: Constant variable values have to be defined along with the declaration and after that it won't change.const are implicitly static, so without creating a class instance we can access them. This has a value at compile time.
ReadOnly: We can define read-only variable values while declaring as well as using the constructor at runtime. Read-only variables can't access without a class instance.
Static readonly: We can define static readonly variable values while declaring as well as only through a static constructor, but not with any other constructor. We can also access these variables without creating a class instance (as static variables).
Static readonly will be better choice if we have to consume the variables in different assemblies. Please check the full details in the below blog post:
Const Strings – a very convenient way to shoot yourself in the foot
静态只读字段在暴露时是有利的
其他程序集的值可能会在更高版本中更改。
例如,假设程序集
X
公开一个常量,如下所示:如果程序集
Y
引用X
并使用此常量,则值 2.3编译时将被烘焙到程序集
Y
中。 这意味着如果稍后将
X
重新编译并将常量设置为 2.4,Y
仍将使用旧值 2.3,直到重新编译
Y
。 静态的readonly 字段避免了这个问题。
另一种看待这个问题的方式是,任何可能的值
根据定义,未来的变化并不是恒定的,因此也应该
不能被表示为一个。
A static readonly field is advantageous when exposing to
other assemblies a value that might change in a later version.
For instance, suppose assembly
X
exposes a constant as follows:If assembly
Y
referencesX
and uses this constant, the value 2.3will be baked into assembly
Y
when compiled. This means thatif
X
is later recompiled with the constant set to 2.4,Y
will stilluse the old value of 2.3 until
Y
is recompiled. A staticreadonly field avoids this problem.
Another way of looking at this is that any value that might
change in the future is not constant by definition, and so should
not be represented as one.
参考:c-sharpcorner
Reference: c-sharpcorner
C# 中的 const 和静态只读字段之间存在细微差别。Net
const 必须在编译时用值进行初始化。
const 默认是静态的,需要用常量值初始化,以后不能修改。
它不能与所有数据类型一起使用。 对于前日期时间。 它不能与 DateTime 数据类型一起使用。
readonly 可以声明为静态,但不是必需的。 声明时无需初始化。 可以使用构造函数一次对其值进行赋值或更改。 所以有可能改变只读字段的值一次(没关系,无论它是否是静态的),这是 const 不可能的。
There is a minor difference between const and static readonly fields in C#.Net
const must be initialized with value at compile time.
const is by default static and needs to be initialized with constant value, which can not be modified later on.
It can not be used with all datatypes. For ex- DateTime. It can not be used with DateTime datatype.
readonly can be declared as static, but not necessary. No need to initialize at the time of declaration. Its value can be assigned or changed using constructor once. So there is a possibility to change value of readonly field once (does not matter, if it is static or not), which is not possible with const.
const:
只读:
const:
readonly:
const(在编译时确定)可以在只读静态不能使用的情况下使用,例如在 switch 语句或属性构造函数中。 这是因为只读字段仅在运行时解析,并且某些代码构造需要编译时保证。 可以在构造函数中计算只读静态,这通常是必不可少且有用的事情。 区别是功能性的,我认为它们的用法也应该如此。
就内存分配而言,至少对于字符串(作为一种引用类型)来说,似乎没有什么区别,因为两者都被实习并且将引用一个实习实例。
就我个人而言,我的默认值是只读静态,因为它对我来说更具语义和逻辑意义,特别是因为大多数值在编译时不需要。 顺便说一句,公共只读静态变量并不罕见或不常见,正如标记的答案所述:例如,
System.String.Empty
就是其中之一。A const (being determined at compile-time) can be used in cases where a readonly static can't, like in switch statements, or attribute constructors. This is because readonly fields are only resolved at run-time, and some code constructs require compile time assurance. A readonly static can be calculated in a constructor, which is often an essential and useful thing. The difference is functional, as should be their usage in my opinion.
In terms of memory allocation, at least with strings (being a reference type), there seems to be no difference in that both are interned and will reference the one interned instance.
Personally, my default is readonly static, as it makes more semantic and logical sense to me, especially since most values are not needed at compile time. And, by the way, public readonly statics are not unusual or uncommon at all as the marked answer states: for instance,
System.String.Empty
is one.如果您可以提供编译时常量,请使用
const
:如果您需要在运行时评估值,请使用
static readonly
:这将给出编译错误,因为这是不可能的在编译时获取值。
Use
const
if you can provide a compile-time constant:Use
static readonly
if you need your value evaluated during run-time:This will give a compile error because it is impossible to get the value at compile-time.
Const、readonly、static readonly - 执行类似操作但有重要区别的关键字:
• Const - 是一个变量,其值是常量并在编译时分配。 您必须为其分配一个值。 默认常量是静态的,我们无法在整个程序中更改 const 变量的值。
• 只读 - 表示我们可以在运行时更改的值,或者我们可以在运行时 更改 const 变量的值。可以在运行时分配它,但只能通过非静态构造函数。
• 静态只读 - 值可以在运行时分配或在编译时分配并在运行时更改时间。 但该变量的值只能在静态构造函数中更改。 并且无法进一步改变。 在执行期间只能更改一次。
您可以在此处找到示例 - https://www.c-sharpcorner.com/UploadFile/c210df/difference- Between-const-readonly-and-static-readonly-in- C 升号/
Const, readonly, static readonly - keywords that perform a similar action but have an important difference:
• Const - is a variable whose value is constant and is assigned at compile time. You must assign a value to it. The default constants are static, and we cannot change the value of the const variable throughout the program.
• Readonly - means a value that we can change at run time, or we can assign it at run time, but only through a non-static constructor.
• Static readonly - values can be assigned at run time or assigned at compile time and changed at run time. But the value of this variable can be changed only in the static constructor. And cannot be changed further. It can only be changed once during execution.
Examples you can find here - https://www.c-sharpcorner.com/UploadFile/c210df/difference-between-const-readonly-and-static-readonly-in-C-Sharp/
声明 const 和 static readonly 之间的另一个区别在于内存分配。
静态字段属于对象的类型,而不是该类型的实例。 因此,一旦第一次引用该类,静态字段将在其余时间“存活”在内存中,并且该类型的所有实例都将引用该静态字段的同一实例。
另一方面,const 字段“属于类型的实例。
如果释放内存对您来说更重要,则更喜欢使用const。如果速度快,那么使用静态只读。
Another difference between declaring const and static readonly is in memory allocation.
A static field belongs to the type of an object rather than to an instance of that type. As a result, once the class is referenced for the first time, the static field would "live" in the memory for the rest of time, and the same instance of the static field would be referenced by all instances of the type.
On the other hand, a const field "belongs to an instance of the type.
If memory of deallocation is more important for you, prefer to use const. If speed, then use static readonly.
顾名思义,常量是不会改变的字段,通常在编译时在代码中静态定义。
只读变量是在特定条件下可以更改的字段。
它们可以在您第一次将它们声明为常量时进行初始化,但通常它们是在构造函数内的对象构造过程中进行初始化的。
在上述情况下,初始化发生后它们无法更改。
静态只读对我来说听起来是一个糟糕的选择,因为如果它是静态的并且永远不会改变,那么只需使用它 public const 即可。 如果它可以改变,那么它就不是常量,然后根据您的需要,您可以使用只读变量或仅使用常规变量。
另外,另一个重要的区别是常量属于类,而只读变量属于实例!
Constants are like the name implies, fields which don't change and are usually defined statically at compile time in the code.
Read-only variables are fields that can change under specific conditions.
They can be either initialized when you first declare them like a constant, but usually they are initialized during object construction inside the constructor.
They cannot be changed after the initialization takes place, in the conditions mentioned above.
Static read-only sounds like a poor choice to me since, if it's static and it never changes, so just use it public const. If it can change then it's not a constant and then, depending on your needs, you can either use read-only or just a regular variable.
Also, another important distinction is that a constant belongs to the class, while the read-only variable belongs to the instance!
有一个重要的问题,在上面的答案中没有提到,并且应该促使您更喜欢“const”,特别是对于“int”,“string”等基本类型。
常量可以用作属性参数< /strong>,静态只读字段不行!
Azure 函数 HttpTrigger,不在属性中使用 HttpMethods 类
如果只有微软对 Http 的 GET、POST、DELETE 等使用常量,
就可以这样写
,但我必须求助于
或使用我自己的常量:
There is one important question, that is not mentioned anywhere in the above answers, and should drive you to prefer "const" especially for basic types like "int", "string" etc.
Constants can be used as Attribute parameters, static readonly field not!
Azure functions HttpTrigger, not using HttpMethods class in attribute
If only microsoft used constants for Http's GET, POST, DELETE etc.
It would be possible to write
But instead I have to resort to
Or use my own constant:
(旁注)当静态应用于方法时,编译的代码不会将“this”参数传递给方法,因此您无法访问对象的实例数据。
在重构期间,所有 const 都可以安全地转换为静态只读,但反之亦然,正如我们在上面看到的,转换后的代码可能会中断,因为某些静态只读变量可以在构造函数中初始化。
(on side note)When static is applied to methods, the complied code does not pass the 'this' parameter to the method and hence you cannot access the instance data of the object.
During Refactoring, All const can be safely converted to Static read only, but not vise versa as we have seen above when converted code may break as some static readonly variable could be initialized in constructors.
我不相信上面提到的另一个区别:
const
和static readonly
值无法获取 CodeLens 在 Visual Studio 中应用于它们IDE。static
仅获取属性 DO 获取应用于它们的 CodeLens。我认为添加 CodeLens 非常有价值。
注意:当前使用 Visual Studio 2022。
One additional difference that I don't believe is mentioned above:
const
andstatic readonly
values don't get CodeLens applied to them in the Visual Studio IDE.static
get only properties DO get CodeLens applied to them.I consider the addition of CodeLens to be quite valuable.
Note: Currently using Visual Studio 2022.
public static readonly
字段有点不寻常;public static
属性(只有get
)会更常见(可能由private static readonly
字段支持)。const
值直接烧录到调用站点中; 这是双刃剑:如果值永远改变,那么 const 就可以 -
零
等构成合理的 consts ;p 除此之外,static
属性更为常见。public static readonly
fields are a little unusual;public static
properties (with only aget
) would be more common (perhaps backed by aprivate static readonly
field).const
values are burned directly into the call-site; this is double edged:If the value will never change, then const is fine -
Zero
etc make reasonable consts ;p Other than that,static
properties are more common.