#603 – Using Constants Can Force Recompilation

Here’s an additional difference between a static readonly field and a constant.  Let’s say that you have a class that includes both a public static readonly field and a public constant.

public static readonly string ReadonlyMotto = "Man's Best Friend";
public const string ConstantMotto = "Man's Best Friend";

Now assume that you have two assemblies, as follows.

At this point, let’s say that you want to change the two elements that contain the dog mottos, i.e. the readonly field and the constant.  So you change the values and re-compile Dog.dll but do not re-compile DogViewer.exe.

At this point, something interesting happens at runtime if you run DogViewer.exe.

  • DogViewer sees the new value of the readonly field
  • DogViewer does not see the new value of the constant

This happens because when you compile code that uses a constant, the value of the constant is included in the generated code.

#339 – Readonly Fields vs. Read-Only Properties

A read-only property in a class is similar to a readonly field.  Both expose a value that users of the class can read, but not write.

A readonly field is defined using the readonly modifier.  A read-only property is defined by including a get accessor for the property, but not a set accessor.

A readonly field can have only a single value, set either at the time that the field is declared, or in a constructor.  A read-only property returns a value that may be different each time the property is read.

Example of a readonly field:

        // Readonly field, initialized in constructor
        public readonly string OriginalName;

        public Dog(string name)
            Name = name;

            // Set readonly field once, in the constructor
            OriginalName = name;

Example of a read-only property:

        public string FormalName
                return string.Format("Sir {0}", Name);

#338 – Static Readonly Fields vs. Constants

A static readonly field in a class is very similar to a constant.  Both expose a constant, static value that is associated with the class, independent of any instances of the class.

We could declare a static readonly field in a Dog class:

        public static readonly string TheDogMotto = "Man's Best Friend";

We could also declare this value as a constant:

        public const string TheDogMotto = "Man's Best Friend";

The value of a constant must be known at compile-time and specified as part of the declaration.

The value of a static readonly field is set at run-time, so it can be different from run to run.  It is specified in either the declaration or within a static constructor.

Use a readonly field for values that you won’t know until run-time or have to calculate.  Use a constant for values that are known and never change.

#337 – Declaring and Using Static readonly Fields

A readonly field in a class can be a static or an instance field.

A static readonly field is a field that has a single read-only value, regardless of the number of instances of the parent class.  Client classes can read from, but not write to, the field.  The field is initialized either as part of the declaration or within a static constructor.

        // Static readonly field, initialized at declaration time
        public static readonly string TheDogMotto = "Man's Best Friend";

        // Static readonly field, initialized in a constructor
        public static readonly uint NumberOfLegs;

        static Dog()
            NumberOfLegs = 4;

Other code can read these fields.

            string motto = Dog.TheDogMotto;
            uint numLegs = Dog.NumberOfLegs;

#336 – Declaring and Using a readonly Field

You can make a field in a class read-only by using the readonly modifier when the field is declared.

In the example below, code that creates or uses instances of the Dog class will be able to read the SerialNumber field, but not write to it.

    public class Dog
        public string Name;
        public int Age;
        public readonly string SerialNumber;

        public Dog(string name, int age, string serNumber)
            Name = name;
            Age = age;
            SerialNumber = serNumber;

You can assign a value to a readonly field in only two different places:

  • In the class’ constructor
  • As part of the field’s declaration
        public readonly string BestFriend = "Man";