关于C#:静态类中const、readonly和get的区别是什么?


what is the difference between const, readonly and get in a static class

本问题已经有最佳答案,请猛点这里访问。

我有个问题。最近我发现自己使用了3行不同的代码,经过仔细检查,它们看起来和感觉都是一样的。

1
2
3
4
5
6
public static class constant
{
    public static readonly int val1 = 5;
    public const int val2 = 5;
    public static int val3 { get { return 5; } }
}

我的问题是,它们是相同的吗?一个应该用在另一个上面吗?如果是这样的话。什么时候?

在Visual Studio中,还有一个额外的问题,为什么它们在IntelliSense中的表示方式都不同?

enter image description here


声明为只读的成员提供了在类的(静态)构造函数中更改的可能性,而常量成员在运行时无法更改。

将字段声明为常量将使其自动静态,引用§10.3.7:

When a field, method, property, event, operator, or constructor
declaration includes a static modifier, it declares a static member.
In addition, a constant or type declaration implicitly declares a
static member.

第三个只是一个只读属性,它总是返回5。

您不应该使用这样的属性,如果可能,为了允许编译器和/或抖动执行它们的优化并帮助其他人读取您的代码,您最好使用const成员(该属性对我来说是一种wtf)。如果需要在程序启动期间初始化的常量值(例如,计算机的内核数),则必须使用静态只读成员。

这是C规范(第10.5.2.1节)中的一个很好的例子:

A static readonly field is useful when a symbolic name for a constant
value is desired, but when the type of the value is not permitted in a
const declaration, or when the value cannot be computed at
compile-time. In the example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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;
    }
}

the Black, White, Red, Green, and Blue members cannot be declared as
const members because their values cannot be computed at compile-time.
However, declaring them static readonly instead has much the same
effect.

还有一个区别(§10.5.2.2):

Constants and readonly fields have different binary versioning
semantics. When an expression references a constant, the value of the
constant is obtained at compile-time, but when an expression
references a readonly field, the value of the field is not obtained
until run-time.

综上所述,它们是非常不同的,即使乍一看它们可能看起来很相似,你应该使用最适合你意图的。


我只是解释你的第一个问题。

成员应该被赋予初始值吗??在编译时,则不能更改。静态只读;成员的值??无需分配初始化,然后分配。预约后不能更改一次。

静态只读成员可以从其所属的类中访问,并且可以分配值。要分配的值的第一个赋值必须完成成员的值,或者应该在事务中进行静态构造函数。


嗨,你可以在这篇文章中找到问题的答案:

静态只读与常量

您还可以检查IL代码并尝试自己比较结果。


const是编译时计算的表达式。编译器可以将该值直接嵌入其使用的每个位置。静态只读将只在运行时进行计算,如果您认为该值稍后可能会发生更改,则此方法非常有用,因为针对您的程序集编译的程序集不会嵌入静态只读值,而静态只读值可能与常量一起发生。注意一些值,如datetime。现在不能存储在常量中,因为它是对必须在运行时完成的属性的计算。您可以使用静态只读,它将类似于常量,但它将在运行时捕获该值。

最后一个属性可以做的不仅仅是返回一个值。它可能是Web服务调用或复杂计算的结果。注意,属性中的代码可能被编译器内联。

您使用哪一个取决于您想要的语义。


在字段定义中使用constreadonly时。const限定符只能与primitive data类型和字符串一起使用。使用时,分配给const字段的值将直接插入到生成的IL代码中的所有引用中。其他程序集也是如此。引用该const字段的其他程序集被编译为直接使用值本身。只读字段是运行时常量。它们在内存中占据了一定的位置,对它们的引用在运行时得到解析,就好像我们引用了一个普通变量一样。实际上,它们是类似于常量的变量。

const:

作为一般规则,尽量避免使用常量,因为该值不仅硬编码到声明它们的程序集中,而且还硬编码到引用常量值的任何程序集中。这会产生一些真正奇怪的问题。

  • 不能是静态的。
  • 值在编译时计算。
  • 仅在声明时初始化。

readonly:

  • 可以是实例级的,也可以是静态的。
  • 值在运行时计算。
  • 可以在声明中或通过构造函数中的代码初始化。

您应该尽可能使用constant字段,但这只适用于基本类型。

当您需要自定义类型(比如您自己的类或结构)时,应该使用public static property

公共字段只在结构中使用,并且我无法回忆任何我看到任何公共静态只读字段的情况。


静态只读可以在constroctor处分配,而const不能分配。此外,getter不必返回常量值,值van是私有成员,可以在类的另一部分中更改,也可以是计算值。

从只读(C引用)

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 as in the following example:

1
public static readonly uint timeStamp = (uint)DateTime.Now.Ticks;

The readonly keyword is a modifier that you can use on fields. When a
field declaration includes a readonly modifier, assignments to the
fields introduced by the declaration can only occur as part of the
declaration or in a constructor in the same class.

来自常量(C参考)

The const keyword is used to modify a declaration of a field or local
variable. It specifies that the value of the field or the local
variable is constant, which means it cannot be modified.

此外,由于它们是不同的编译时对象,因此在IntelliSense中是不同的