'Static readonly' vs. 'const'

前端 未结 18 2620
旧巷少年郎
旧巷少年郎 2020-11-22 04:07

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

相关标签:
18条回答
  • 2020-11-22 05:06

    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.

    0 讨论(0)
  • 2020-11-22 05:07

    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.

    0 讨论(0)
  • 2020-11-22 05:07

    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

    [HttpTrigger(AuthorizationLeve.Anonymous,  HttpMethods.Get)] // COMPILE ERROR: static readonly, 
    

    But instead I have to resort to

    [HttpTrigger(AuthorizationLeve.Anonymous,  "GET")] // STRING
    

    Or use my own constant:

    public class HttpConstants
    {
        public const string Get = "GET";
    }
    
    [HttpTrigger(AuthorizationLeve.Anonymous,  HttpConstants.Get)] // Compile FINE!
    
    0 讨论(0)
  • 2020-11-22 05:08

    public static readonly fields are a little unusual; public static properties (with only a get) would be more common (perhaps backed by a private static readonly field).

    const values are burned directly into the call-site; this is double edged:

    • it is useless if the value is fetched at runtime, perhaps from config
    • if you change the value of a const, you need to rebuild all the clients
    • but it can be faster, as it avoids a method call...
    • ...which might sometimes have been inlined by the JIT anyway

    If the value will never change, then const is fine - Zero etc make reasonable consts ;p Other than that, static properties are more common.

    0 讨论(0)
  • 2020-11-22 05:09

    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.

    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 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.

    0 讨论(0)
  • 2020-11-22 05:10

    const and readonly 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. A readonly field enables additional scenarios in which some code must be run during construction of the type. After construction, a readonly field cannot be changed.

    For instance, const members can be used to define members like:

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

    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:

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

    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.

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

    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:

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

    and a different developer wrote code that relied on A:

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

    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.

    0 讨论(0)
提交回复
热议问题