What is the difference between const and readonly in C#?

前端 未结 30 2673
挽巷
挽巷 2020-11-22 05:05

What is the difference between const and readonly in C#?

When would you use one over the other?

相关标签:
30条回答
  • 2020-11-22 05:26

    Just to add, readonly for reference types only makes the reference read only not the values. For example:

    public class Const_V_Readonly
    {
      public const int I_CONST_VALUE = 2;
      public readonly char[] I_RO_VALUE = new Char[]{'a', 'b', 'c'};
    
      public UpdateReadonly()
      {
         I_RO_VALUE[0] = 'V'; //perfectly legal and will update the value
         I_RO_VALUE = new char[]{'V'}; //will cause compiler error
      }
    }
    
    0 讨论(0)
  • 2020-11-22 05:26

    Yet another gotcha: readonly values can be changed by "devious" code via reflection.

    var fi = this.GetType()
                 .BaseType
                 .GetField("_someField", 
                           BindingFlags.Instance | BindingFlags.NonPublic);
    fi.SetValue(this, 1);
    

    Can I change a private readonly inherited field in C# using reflection?

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

    There is a gotcha with consts! If you reference a constant from another assembly, its value will be compiled right into the calling assembly. That way when you update the constant in the referenced assembly it won't change in the calling assembly!

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

    This explains it. Summary: const must be initialized at declaration time, readonly can be initialized on the constructor (and thus have a different value depending on the constructor used).

    EDIT: See Gishu's gotcha above for the subtle difference

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

    CONST

    1. const keyword can be applied to fields or local variables
    2. We must assign const field at time of declaration
    3. No Memory Allocated Because const value is embedded in IL code itself after compilation. It is like find all occurrences of const variable and replace by its value. So the IL code after compilation will have hard-coded values in place of const variables
    4. Const in C# are by default static.
    5. The value is constant for all objects
    6. There is dll versioning issue - This means that whenever we change a public const variable or property , (In fact, it is not supposed to be changed theoretically), any other dll or assembly which uses this variable has to be re-built
    7. Only C# built-in types can be declared as constant
    8. Const field can not be passed as ref or out parameter

    ReadOnly

    1. readonly keyword applies only to fields not local variables
    2. We can assign readonly field at the time of declaration or in constructor,not in any other methods.
    3. dynamic memory allocated for readonly fields and we can get the value at run time.
    4. Readonly belongs to the object created so accessed through only instance of class. To make it class member we need to add static keyword before readonly.
    5. The value may be different depending upon constructor used (as it belongs to object of the class)
    6. If you declare a non-primitive types (reference type) as readonly only reference is immutable not the object it contains.
    7. Since the value is obtained at run time, there is no dll versioning problem with readonly fields/ properties.
    8. We can pass readonly field as ref or out parameters in the constructor context.
    0 讨论(0)
  • 2020-11-22 05:28

    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 = r;
            green = g;
            blue = 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 = r;
            green = g;
            blue = 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)
提交回复
热议问题