3.25. Initializing a Constant Field at Runtime

Problem

A field marked as const can be initialized only at compile time. You need to initialize a field at runtime to a valid value, not at compile time. This field must then act as if it were a constant field for the rest of the application’s life.

Solution

When declaring a constant value in your code, there are two choices. You can use a readonly field or a const field. Each has its own strengths and weaknesses. However, if you need to initialize a constant field at runtime, you should use a readonly field:

public class Foo
{
    public readonly int bar;

    public Foo( ) {}

    public Foo(int constInitValue)
    {
        bar = constInitValue;
    }

    // Rest of class...
}

This is not possible using a const field. A const field can be initialized only at compile time:

public class Foo
{
    public const int bar;        // This line causes a compile-time error

    public Foo( ) {}

    public Foo(int constInitValue)
    {
        bar = constInitValue;    // This line also causes a compile-time error
    }

    // Rest of class...
}

Discussion

A readonly field allows initialization to take place only in the constructor at runtime, whereas a const field must be initialized at compile time. Therefore, implementing a readonly field is the only way to allow a field that must be constant to be initialized at runtime.

There are only two ways to initialize a readonly field. The first is by adding an initializer to the field itself:

public readonly int bar = 100;

The second way is to initialize the readonly field through a constructor. This is demonstrated through the code in the Solution to this recipe.

If you look at the following class:

public class Foo
{
        public readonly int x;
        public const int y = 1;

        public Foo( ) {}

        public Foo(int roInitValue)
        {
        x = roInitValue;
        }

        // Rest of class...
}

You’ll see it is compiled into the following IL:

.class public auto ansi beforefieldinit Foo
    extends [mscorlib]System.Object
{
.field public static literal int32 y = int32(0x00000001)  //<<-- const field
               .field public initonly int32 x                            //<<-- readonly field
.method public hidebysig specialname rtspecialname 
        instance void  .ctor(int32 input) cil managed
{
    // Code size       14 (0xe)
    .maxstack  8
//001659:         }
//001660: }

//001666: public class Foo
//001667: {
//001668:         public readonly int x;
//001669:         public const int y = 1;
//001670:         
//001671:         public Foo(int roInitValue)
    IL_0000:  ldarg.0
    IL_0001:  call       instance void [mscorlib]System.Object::.ctor( )
//001672:         {
//001673:                 x = input;
    IL_0006:  ldarg.0
    IL_0007:  ldarg.1
    IL_0008:  stfld      int32 Foo::x
//001674         }
    IL_000d:  ret
} // end of method Foo::.ctor

} // end of class Foo

Notice that a const field is compiled into a static field, and a readonly field is compiled into an instance field. Therefore, you need only a class name to access a const field.

Tip

A common argument against using const fields is that they do not version as well as readonly fields. If you rebuild a component that defines a const field, and the value of that const changes in a later version, any other components that were built against the old version won’t pick up the new value.

The following code shows how to use a readonly field:

Foo obj1 = new Foo(100);
Console.WriteLine(obj1.bar);

Those two lines compile into the following IL:

IL_0013:  ldc.i4     0xc8
IL_0018:  newobj     instance void Foo::.ctor(int32)
IL_001d:  stloc.1
IL_001e:  ldloc.1
IL_001f:  ldfld      int32 Foo::bar

Since the const field is already compiled into the application as a static member field, only one simple IL instruction is needed to use this const field at any point in the application:

IL_0029:  ldc.i4.1

Notice that the compiler compiled away the const field and uses the value it was initialized to, which is 1. This is faster than using a readonly field. However, const fields are inflexible as far as versioning is concerned.

See Also

See the “const” and “readonly” keywords in the MSDN documentation.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.219.71.21