const,readonly和get in static class之间的区别是什么

时间:2013-09-02 18:25:09

标签: c#

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

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

我的问题是,它们是否相同,是否应该使用另一个?如果是这样。当α

作为视觉工作室中的一个额外问题,为什么它们在智能感知中的表现方式不同?

enter image description here

7 个答案:

答案 0 :(得分:9)

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

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

  

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

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

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

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

  

静态只读字段在常量的符号名称时很有用   期望值,但是当a中不允许值的类型时   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;
    }
}
  

黑色,白色,红色,绿色和蓝色成员不能声明为   const成员,因为它们的值无法在编译时计算。   然而,将它们声明为静态只读而已大致相同   影响。

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

  

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

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

答案 1 :(得分:0)

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

来自readonly (C# Reference)

  

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

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

readonly关键字是一个可以在字段上使用的修饰符。当一个   字段声明包括一个只读修饰符,赋值给   声明引入的字段只能作为其中的一部分出现   声明或在同一类的构造函数中。

来自const (C# Reference)

  

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

此外,intellisense中的不同之处在于它们是不同的编译时对象

答案 2 :(得分:0)

您应该尽可能使用const ant字段 - 但这仅适用于基本类型。

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

公共字段仅在结构中使用,我不记得任何我看到任何公共静态只读字段的情况。

答案 3 :(得分:0)

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

const:

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

  • 不能是静止的。
  • 在编译时评估值。
  • 仅在声明时宣传。

readonly:

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

答案 4 :(得分:0)

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

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

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

答案 5 :(得分:0)

您好,您将在本文中找到您的问题的答案:

Static readonly vs const

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

答案 6 :(得分:0)

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

常量;成员应该在编译时给出初始值,然后它们不能被更改。静态只读;成员的值不必分配为初始化,然后分配。预约后不能更改一次。

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