首页 文章

静态只读与const

提问于
浏览
1241

我读过有关 conststatic readonly 字段的内容 . 我们有一些只包含常量值的类 . 用于我们系统中的各种事物 . 所以我想知道我的观察是否正确:

对于所有公开的事物,这些常数值是否总是 static readonly ?并且只对内部/受保护/私有值使用 const

您有什么推荐的吗?我是否可能甚至不使用 static readonly 字段,而是使用属性?

15 回答

  • 180

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

    Short and clear MSDN reference here

  • 3

    其他一些事情

    const int a

    • 必须初始化

    • 初始化必须在编译时

    readonly int a

    • 可以使用默认值,而无需初始化

    • 初始化可以在运行时

  • 12

    常量类似于名称暗示,字段不会更改,通常在编译时在代码中静态定义 .

    只读变量是在特定条件下可以更改的字段 .

    当你第一次将它们声明为常量时,它们可以被初始化,但通常它们在构造函数内的对象构造期间被初始化 .

    在初始化发生后,在上述条件下,它们无法更改 .

    静态只读对我来说是一个糟糕的选择,因为它是静态的并且它永远不会改变,所以只需使用它就是公共const,如果它可以改变那么它不是常数然后,根据你的需要,你可以使用read - 只是一个常规变量 .

    另外,另一个重要的区别是常量属于类,而只读变量属于实例!

  • 7

    public static readonly 字段有点不寻常; public static 属性(仅使用 get )会更常见(可能由 private static readonly 字段支持) .

    const 值直接刻录到呼叫站点;这是双刃:

    • 如果在运行时获取值,则可能无法从config获取

    • 如果更改const的值,则需要重建所有客户端

    • 但它可以更快,因为它避免了方法调用...

    • ......无论如何,JIT有时可能已将其内联

    如果值将 never 更改,则const很好 - Zero 等进行合理的consts; p除此之外, static 属性更常见 .

  • 0

    如果Consumer在不同的程序集中,我会使用 static readonly . 将 const 和Consumer放在两个不同的程序集中是shoot yourself in the foot的好方法 .

  • 2

    Const :const变量值必须与声明一起定义,之后它不会改变 . const are implicitly static so without creating class instance we can access them. 这在编译时有一个值

    ReadOnly :我们可以在声明以及在运行时使用构造函数时定义的只读变量值 . readonly变量无法访问没有类实例 .

    Static readonly :静态只读变量值我们可以在声明时定义,只能通过静态构造函数来定义,但不能与任何其他构造函数一起定义 . 这些变量也可以在不创建类实例的情况下访问(作为静态变量) .

    如果我们必须使用不同程序集中的变量,静态只读将是更好的选择 . 请检查下面链接中的完整详细信息

    https://www.stum.de/2009/01/14/const-strings-a-very-convenient-way-to-shoot-yourself-in-the-foot/

  • 85

    Const:Const只不过是“常量”,这是一个变量,其值在编译时是常量 . 并且必须为其分配值 . 默认情况下,const是静态的,我们不能在整个程序中更改const变量的值 . 静态ReadOnly:静态只读类型变量的值可以在运行时分配,也可以在编译时分配,并在运行时更改 . 但是这个变量的值只能在静态构造函数中更改 . 而且无法进一步改变 . 它只能在运行时更改一次

    参考:c-sharpcorner

  • 855

    Static Read Only :可以在运行时通过 static 构造函数更改值 . 但不是通过成员函数 .

    Constant :默认为 static . Value 不能从任何地方改变(Ctor,Function,runtime等no-where) .

    Read Only :可以在运行时通过构造函数更改值 . 但不是通过成员函数 .

    你可以看一下我的回购:C# property types .

  • 20

    C#.Net中const和静态只读字段之间存在细微差别

    const必须在编译时用值初始化 .

    const默认是静态的,需要用常量值初始化,以后不能修改 . 它不能与所有数据类型一起使用 . 对于前日期时间 . 它不能与DateTime数据类型一起使用 .

    public const DateTime dt = DateTime.Today;  //throws compilation error
    public const string Name = string.Empty;    //throws compilation error
    public static readonly string Name = string.Empty; //No error, legal
    

    readonly可以声明为static,但不是必需的 . 没有必要在申报时初始化 . 可以使用构造函数一次分配或更改其值 . 所以有可能改变readonly字段的值一次(无关紧要,如果它是静态的),这是const不可能的 .

  • 15

    constreadonly 是相似的,但它们并不完全相同 .

    const 字段是编译时常量,表示该值可以在编译时计算 . readonly 字段允许在构造类型期间必须运行某些代码的其他方案 . 构建后,无法更改 readonly 字段 .

    例如, const 成员可用于定义以下成员:

    struct Test
    {
        public const double Pi = 3.14;
        public const int Zero = 0;
    }
    

    因为像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);
    }
    

    但是,通过交换黑白值,没有什么能阻止Color的客户端使用它 . 不用说,这会导致Color类的其他客户端惊慌失措 . “只读”功能解决了这种情况 .

    通过在声明中简单地引入 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);
    }
    

    有趣的是,const成员总是静态的,而readonly成员可以是静态的,也可以不是静态的,就像常规字段一样 .

    可以将单个关键字用于这两个目的,但这会导致版本控制问题或性能问题 . 假设我们为此(const)使用了一个关键字,开发人员写道:

    public class A
    {
        public static const C = 0;
    }
    

    而另一个开发人员编写的代码依赖于A:

    public class B
    {
        static void Main() => Console.WriteLine(A.C);
    }
    

    现在,生成的代码能否依赖于A.C是编译时常量的事实?即,A.C的使用是否可以简单地用值0代替?如果对此说“是”,那么这意味着A的开发人员无法改变A.C初始化的方式 - 这将未经许可将A的开发人员联系起来 .

    如果你对这个问题说“不”,那么就会错过重要的优化 . 也许A的作者肯定A.C永远是零 . const和readonly的使用允许A的开发者指定意图 . 这样可以获得更好的版本控制行为和更好的性能 .

  • 24

    常量:

    • 值应在声明时给出

    • 编译时间常数

    只读:

    • 值可以在声明时或在运行时使用构造函数给出 . 值可以根据使用的构造函数而变化 .

    • 运行时常数

  • 6

    我的偏好是尽可能使用 const ,如上所述,这仅限于文字表达或不需要评估的东西 .

    如果我对这个限制感到热烈,那么我会回避 static readonly ,但有一点需要注意 . 我通常会使用带有getter和后备 private static readonly 字段的公共静态属性,如Marc提到here .

  • 210

    这只是对其他答案的补充 . 我不会重复它们(现在四年后) .

    在某些情况下, const 和非const具有不同的语义 . 例如:

    const int y = 42;
    
    static void Main()
    {
      short x = 42;
      Console.WriteLine(x.Equals(y));
    }
    

    打印出 True ,而:

    static readonly int y = 42;
    
    static void Main()
    {
      short x = 42;
      Console.WriteLine(x.Equals(y));
    }
    

    写道 False .

    原因是方法x.Equals有两个重载,一个接收 shortSystem.Int16 ),另一个接收 objectSystem.Object ) . 现在问题是一个或两个是否适用于我的 y 参数 .

    y 是编译时常量(文字), const 情况时,如果 int 是常量,并且C#编译器验证其值是否在内,则确实存在从 int 到_258353的隐式转换变得很重要 . short 的范围( 42 是) . 请参阅C#语言规范中的Implicit constant expression conversions . 因此必须考虑两种重载 . 重载 Equals(short) 是首选(任何 shortobject ,但并非所有 object 都是 short ) . 所以 y 转换为 short ,并使用该重载 . 然后 Equals 比较两个相同值的 short ,并给出 true .

    y 不是常量时,不存在从 intshort 的隐式转换 . 这是因为一般情况下 int 可能太大而无法适应 short . (显式转换确实存在,但我没有说 Equals((short)y) ,所以这不相关 . )我们看到只有一个重载适用, Equals(object) . 所以 y 被装箱到 object . 然后 EqualsSystem.Int16System.Int32 进行比较,并且由于运行时类型甚至不同意,因此将产生 false .

    我们得出结论,在一些(罕见的)情况下,将 const 类型成员更改为 static readonly 字段(或者在可能的情况下将其他方式更改)可以更改程序的行为 .

  • 0

    需要注意的一点是const仅限于原始/值类型(异常是字符串)

  • 158

    当向其他程序集公开可能在更高版本中更改的值时,静态只读字段是有利的 .

    例如,假设程序集 X 公开一个常量,如下所示:

    public const decimal ProgramVersion = 2.3;
    

    如果程序集 Y 引用 X 并使用此常量,则值2.3将在编译时被烘焙到程序集 Y 中 . 这意味着如果 X 稍后在常量设置为2.4的情况下重新编译, Y 仍将使用旧值2.3,直到重新编译 Y . 静态只读字段可以避免此问题 .

    另一种看待这种情况的方法是,根据定义,未来可能发生变化的任何值都不是恒定的,因此不应该表示为一个 .

相关问题