19

I have a question. Lately I have caught myself using 3 different lines of code which upon closer inspection looks and feels the same.

public static class constant
{
    public static readonly int val1 = 5;
    public const int val2 = 5;
    public static int val3 { get { return 5; } }
}

my question is, are they the same and should one be used over another? if so. When?

also as a extra question in visual studio why are they all represented differently in intellisense?

enter image description here

4

7 回答 7

9

声明为 readonly 的成员可以在类的(静态)构造函数中进行更改,而 const 成员不能在运行时更改。

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

当字段、方法、属性、事件、运算符或构造函数声明包含静态修饰符时,它声明一个静态成员。此外,常量或类型声明隐式声明了一个静态成员。

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

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

这是来自 C# 规范(§10.5.2.1)的一个很好的例子:

当需要常量值的符号名称,但在 const 声明中不允许该值的类型,或者无法在编译时计算该值时,静态只读字段很有用。在示例中

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

Black、White、Red、Green 和 Blue 成员不能声明为 const 成员,因为它们的值不能在编译时计算。但是,将它们声明为 static readonly 具有相同的效果。

还有另一个区别(§10.5.2.2):

常量和只读字段具有不同的二进制版本语义。当表达式引用一个常量时,该常量的值是在编译时获得的,但是当一个表达式引用一个只读字段时,该字段的值直到运行时才获得。

所以,总而言之,它们是非常不同的,即使乍一看它们可能看起来很相似,你应该使用最适合你意图的那个。

于 2013-09-02T18:35:45.707 回答
0

Hi you will find the answer for your questions in this post:

Static readonly vs const

You can also check the IL code and trying to compare the result by your self.

于 2013-09-02T18:39:30.897 回答
0

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

const:

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

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

readonly:

  • 可以是实例级的或静态的。
  • 在运行时评估值。
  • 可以在声明中初始化,也可以通过构造函数中的代码初始化。
于 2013-09-02T18:33:34.210 回答
0

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

常量;成员应该在编译时被赋予初始值,然后他们不能被改变。静态只读;成员的值不一定要赋值才能初始化,然后赋值。预约后一次不可更改。

静态只读成员可以从它们所属的类中访问,并且可以分配值。必须先完成要分配成员值的值的分配,否则应在事务中进行静态构造函数。

于 2013-09-02T18:46:26.463 回答
0

Const 是在编译时计算的表达式。编译器可以将值直接嵌入到它使用的每个地方。静态只读只会在运行时评估,如果您认为该值可能会在以后更改,因为针对您编译的程序集不会嵌入静态只读值,这可能会发生在 const 中。请注意,某些值(例如 DateTime.Now)不能存储在 const 中,因为它是对必须在运行时完成的属性的评估。您可以使用静态只读,它类似于 const 但它会在运行时捕获值。

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

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

于 2013-09-02T18:37:07.427 回答
0

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

只读(C# 参考)

readonly 关键字与 const 关键字不同。const 字段只能在字段声明时进行初始化。只读字段可以在声明或构造函数中初始化。因此,只读字段可以具有不同的值,具体取决于使用的构造函数。此外,虽然 const 字段是编译时常量,但 readonly 字段可用于运行时常量,如下例所示:

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

readonly 关键字是可以在字段上使用的修饰符。当字段声明包含只读修饰符时,对声明引入的字段的赋值只能作为声明的一部分或在同一类的构造函数中发生。

来自const(C# 参考)

const 关键字用于修改字段或局部变量的声明。它指定字段或局部变量的值是常数,这意味着它不能被修改。

此外,在智能感知中它们是不同的,因为它们是不同的编译时对象

于 2013-09-02T18:28:33.753 回答
0

您应该尽可能使用constant 字段 - 但这仅适用于原始类型。

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

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

于 2013-09-02T18:28:39.927 回答