Archive

Archive for the ‘OOP’ Category

Type Initialisers

December 18, 2006 Leave a comment

Following my earlier post on instance constructors, I am going to cover the “Type Initialisers” this time. 

Unlike instance constructors, which are created by the compiler if none is defined by the developer, types do not necessarily have an initialiser. Let’s have a look at our first example. The following screenshot shows how the details of the ApplicationController class are displayed in Ildasm

public class ApplicationController
{
    private static ApplicationController instance;
}

 

Type initialiser is mapped to the .cctor method (instance constructors are mapped to .ctor). Since the ApplicationController class does not have any type initialiser (inline static field initialiser or static constructor), .cctor is not generated. The compiler emits the .cctor only if there are any inline static field initialisers or if the developer has defined a static
constructor for the class.  

public class ApplicationController
{
    private static ApplicationController instance = new ApplicationController
();

We have now added a static field initialiser to the ApplicationController class so Ildasm shows the .cctor statement, which represents the type initialiser. 

 

And this is the generated IL code: 

.method private
hidebysig specialname rtspecialname static

        void .cctor()
cil managed
{
    // Code size 11 (0xb)
    .maxstack 8
    IL_0000: newobj instance void StaticConstructorSample.ApplicationController::.ctor()
    IL_0005: stsfld class StaticConstructorSample.ApplicationController
StaticConstructorSample.ApplicationController::’instance’
    IL_000a: ret
} // end of method ApplicationController::.cctor
 

As you may notice, static constructors are private (so that only CLR can call them) and you cannot specify any access modifier for the static constructor. Each type
can have only one static constructor, which has to be parameter-less. It is good to know that both value types and reference types can have type initialisers. 

Note: You can actually force the type initialiser for a specific type to be executed by calling the RunClassConstructor method on System.Runtime.CompilerServices.RuntimeHelpers. 

If a type has both inline static field initialisers and a static constructor, the compiler will inject the inline static field initialisers (in the textual order in which they appear in the type declaration) at the beginning of the type initialiser. Inline static field initialisers can reference other static members (static properties, methods or fields). The compiler then emits the code for the static constructor as defined by the type author. 

The following example shows how this works: 

public class ApplicationController
{
    private static ApplicationController instance = new ApplicationController();
    private static Dictionary<string, object> cache = null;
   
    static ApplicationController()
    {
        Console.WriteLine(“Type ApplicationController initialised.”);
    }

————————
.method private hidebysig specialname rtspecialname static 
        void .cctor()
cil managed
{
   
// Code size 30 (0x1e)
   
.maxstack 8
   
IL_0000: newobj instance void StaticConstructorSample.ApplicationController::.ctor()
   
IL_0005: stsfld class StaticConstructorSample.ApplicationController
StaticConstructorSample.ApplicationController::’instance’
   
IL_000a: ldnull
   
IL_000b: stsfld class [mscorlib]System.Collections.Generic.Dictionary`2<string,object>
StaticConstructorSample.ApplicationController::cache
   
IL_0010: nop
   
IL_0011: ldstr “Type ApplicationController
initialised.”
   
IL_0016: call void [mscorlib]System.Console::WriteLine(string)
   
IL_001b: nop
   
IL_001c: nop
    IL_001d: ret
} // end of method ApplicationController::.cctor

 

If a type does not have a static constructor, the compiler marks the type with “beforefieldinit”. This allows the CLR to perform a lazy initialisation on that type. This means the CLR has the option of not running the type initialiser until the first access to any static field of the type. So accessing an instance member does not necessarily result in execution of the type initialiser (unless that instance member references a static field of that type). 

Let’s revisit our earlier example where we did not have a static constructor and see how the ApplicationController class is compiled to the IL code: 

public class ApplicationController
{
   
private static ApplicationController instance = new ApplicationController();
}
————————
.class public auto ansi beforefieldinit
StaticConstructorSample.ApplicationController
    extends [mscorlib]System.Object
{
} // end of class StaticConstructorSample.ApplicationController

 

However, if the type has a static constructor (even if it is empty), the compiler will not mark the class with “beforefieldinit”. The impact is that the type initialiser will run just before the very first access to either instance or type members of the type. This means the CLR has to make sure the type initialiser is called before any access to the type in the current application domain. 

public class ApplicationController
{
   
private static ApplicationController instance = new ApplicationController
();

     // This will prevent the compiler from emitting [beforefieldinit] for this class
   
static
ApplicationController()
   {
   }
}
————————
.class public auto ansi StaticConstructorSample.ApplicationController
   
extends [mscorlib]System.Object
{
} // end of class StaticConstructorSample.ApplicationController
  

As you can see, “beforefieldinit” is missing from the IL code this time. There is currently no way for C# developers to specify whether “beforefieldinit” should be emitted for a specific type. The C# compiler just looks for the static constructor for the type and if it finds it, it does not mark the type as “beforefieldinit”.
Otherwise, it will mark the type as “beforefieldinit”. 

The Standard ECMA-335 [page 37] accurately defines the semantics for executing the
type initialiser: 


The semantics of when and what triggers execution of such type initialization methods,
is as follows:
1. A type can have a type-initializer method, or not.
2. A type can be specified as having a relaxed semantic for its type-initializer method (for convenience below, we call this relaxed semantic BeforeFieldInit).
3. If marked BeforeFieldInit then the type’s initializer method is executed at, or sometime before, first access to any static field defined for that type.
4. If not marked BeforeFieldInit then that type’s initializer method is executed at (i.e., is triggered by):
• first access to any static field of that type, or
• first invocation of any static method of that type or
• first invocation of any constructor for that type.
5. Execution of any type’s initializer method will not trigger automatic execution of any initializer
methods defined by its base type, nor of any interfaces that the type implements


One may ask how the compiler knows whether the type initialiser is run in the current application domain already? Well, it doesn’t because it can’t. This is the responsibility of the JIT compiler to emit a call to the type
initialiser if it is not executed in the current application domain. As you can imagine, this can be costly in terms of performance so if static field initialisers satisfy your requirements, do not create a static constructor for your type. 

Since static constructors are visible to all threads in the current application domain, it is possible that code in more than one thread force the type to be initialised but CLR has to make sure the type initialiser is run only once. In order to do this, the calling thread acquires a synchronisation lock on that type and only the
first call to the type constructor actually results in execution of the constructor. All other threads will notice that the constructor has already been executed. The way the CLR deals with concurrent access to the type initialiser provides an easy and safe way of implementing the Singleton pattern. 

Categories: .NET Framework, OOP

Instance Constructors

November 28, 2006 1 comment

It’s construction time! Read this post if you want to refresh your mind on how object construction works. In this post, I will focus on instance constructors in C# and will leave the static constructors (aka type initialisers) to the next post.

Every time you use the new keyword to instantiate an object, the instance constructor of the class is called to initialise the object before it is used.

Each class can have multiple instance constructors with different signatures and access modifiers. If you do not provide an instance constructor for your class, C# compiler will create one for you. The access modifier for the default constructor will be public unless you are defining an abstract class where the access modifier will be set to ‘protected’ (‘family’ in IL terminology).

public class Customer
{
}
—————————–
.method public hidebysig specialname rtspecialnameinstance void .ctor() cil managed
{
  // Code size 7 (0×7)
  .maxstack 8
  IL_0000: ldarg.0
  IL_0001: call instance void [mscorlib]System.Object::.ctor()
  IL_0006: ret
} // end of method Customer::.ctor

This means that all classes have at least one constructor defined when compiled to IL, with one exception: if you define your class as static, the compiler will not create a default constructor. In fact, you will get a compile-time error if you explicitly define an instance constructor for a static class, which makes sense.

When compiled to IL, instance constructors are emitted as .ctor methods. The compiler first generates the initialisation code for the instance fields, if there are any. Instance field initialisers are injected into the very beginning of the constructor. Fields are inistialised in the same sequence as they are defined in the class and cannot reference any other instance members (although they can reference the static members of the class).

Now let’s see how instance field initialisers look like when compiled to the IL code:

public class Customer
{
  public int EmployeeId = 0;
  public string DepartmentId =
“”
;
}
———————
.method public hidebysig specialname rtspecialname 
        in
stance void
.ctor() cil managed
{
  // Code size 26 (0x1a)
  .maxstack 8
  IL_0000: ldarg.0
  IL_0001: ldc.i4.0
  IL_0002: stfld int32 ConstructorSamples.Customer::EmployeeId
  IL_0007: ldarg.0
  IL_0008: ldstr
“”
  IL_000d: stfld string ConstructorSamples.Customer::DepartmentId
  IL_0012: ldarg.0
  IL_0013: call instance void [mscorlib]System.Object::.ctor()
  IL_0018: nop
  IL_0019: ret
} // end of method Customer::.ctor

You may also notice that Customer’s constructor is calling the constructor of System.Object. Before you can create an instance of any object, its base class needs to be constructed first. This goes all the way up to System.Object (in this case System.Object was the immediate parent). So right after emitting the code to initialise the instance fields, the compiler emits an instruction to call the base class’s constructor. In order to do so, it looks at the definition of the constructor to see whether it explicitly mentions any specific constructor on the base class (using the base keyword). If it does, it calls the specified constructor on the base class. Otherwise, it calls the parameterless constructor on the base class. This is also the case if the child class doesn’t have any constructor. You will get a compile time error if you do not provide a constructor for your class and the base class does not have a parameterless constructor.

Instead of using the base keyword, you can also use this, which allows you to call another constructor on the same class rather than the base class. You can chain the constructors on the same class but eventually, the last constructor in the chain needs to call the base class’s constructor.

Something that you need to take into account when overloading the constructor on a type is that inline field initialisers are injected into evey single contructor on the class, unless a constructor is using  this keyword to call another constructor on the same class. So the compiled IL code becomes larger in size if you have lots of field initialisers in a class with multiple constuctor overloads. In most cases you don’t need to be worried about this but if you are, you can chain the constructors by using this keyword.

So we saw how compiler injects inline field initialisation logic and the call to the base class construcor into the IL code. In the last step, the compiler emits the implementation of the constructor as defined by the developer. In the next example, the Customer class inherits from Person, which has a parameterised constructor. Since we have defined the parameterised constructor for Person, the compiler does not create a default one for us. This means the Customer’s constructor has to specify which constructor should be called on the Person class when an instance of Customer is being created.

public class Person
{
  public Person(string knownName)
  {
  }
}

public class Customer: Person
{
  public int EmployeeId = 0;
  public string DepartmentId = “”;
  public Customer(string firstName, string lastName): base(firstName + ” “ + lastName)
  {
    Console.WriteLine(“Customer created”);
  }
}
———————
.method public hidebysig specialname rtspecialname        instance void
.ctor(string firstName, string lastName) cil managed

{
 
// Code size 51 (0×33)
  .maxstack 8
  IL_0000: ldarg.0
  IL_0001: ldc.i4.0
  IL_0002: stfld int32 ConstructorSamples.Customer::EmployeeId
  IL_0007: ldarg.0
  IL_0008: ldstr “”
  IL_000d: stfld string ConstructorSamples.Customer::DepartmentId
  IL_0012: ldarg.0
  IL_0013: ldarg.1
  IL_0014: ldstr ” “
  IL_0019: ldarg.2
  IL_001a: call string [mscorlib]System.String::Concat(string,string,
string)
  IL_001f:
call instance void ConstructorSamples.Person::.ctor(string)
  IL_0024:
nop
  IL_0025: nop
  IL_0026: ldstr
“Customer created”
  IL_002b: call
void [mscorlib]System.Console::WriteLine(string)
  IL_0030: nop
  IL_0031: nop
  IL_0032: ret
>} // end of method Customer::.ctor 

So to wrap it up: the compiled code initialises the member variables first, then calls the base class’s constructor and finally emits the actual constructor code.

Myth: Instance constructor are always run before any other method on that instance.

- Instance constructors are not run when a class is deserialised.
- The overridden methods in the class may be executed before the constructor. This happens if the constructor of the base class calls any virtual methods that are overridden in a child class. Let’s see how this can happen…

public class Person
{
  public Person()
  {
    Console.WriteLine(“Person created”);
    Load();
  }

  protected virtual void Load()
  {
    Console.WriteLine(“Person loaded”);
  }
}
———————
public class Employee: Person
{
  public Employee()
  {
    Console.WriteLine(“Employee created”);
  }

  protected override void Load()
  {
    Console.WriteLine(“Employee loaded”);
 
}
}
———————

Now, if your create an instance of the Employee class by running the following line of code:

Employee
employee = new Employee();

You will get the following result, which may not be desirable.

Person created
Employee loaded
Employee created

In order to avoid the confusion and potential logical errors, it is a good development practice not to call a virtual method in the instance constructor. This should be considered as an anti-pattern for the Template Method pattern: Using the constructor as the “Template Method” for calling virtual operations on a base class.

Categories: .NET Framework, OOP
Follow

Get every new post delivered to your Inbox.