Common Type System—Constructors and Instantiation
Constructors and Instantiation
Instances of types must be created before they are used, a process known as instantiation. An instance is
ordinarily constructed by invoking its constructor with the newobj instruction, whose job it is to initialize
the state of an instance before making it available to other code. Value types support implicit initialization
by simple zeroing out of their bits, for example using the IL instruction initobj, by assigning 0, or by
relying on the default local and field initialization behavior. Types can have any number of constructors,
which are special types of methods with a void return type and each of which is overloaded as with any
other method (i.e., by its parameters).
When the CLR allocates a new object, it does so by first creating space for it on the GC heap. It then invokes your constructor, passing any arguments supplied to the
newobj instruction using an activation frame. It is then the responsibility of your constructor code to
ensure that, when the constructor exits, your type has been fully initialized into a usable state. There
might be additional operations necessary in order to progress to other states, but if a constructor completes
successfully, the instance should be usable and explicitly not corrupt.
Constructors are named .ctor in the IL representation, although C#, for instance, uses a simpler syntax.
The format is to use the type name as though it were a method name, omitting any type of return type
specification (a syntax borrowed from C++). For example, this snippet of code creates a constructor
which initializes some instance state:
class Customer { static int idCounter; private int myId; private string name; public Customer(string name) { if (name == null) throw new ArgumentNullException(“name”); this.myId = ++idCounter; this.name = name; } // ... }
This is compiled into an instance void . ctor(string) method in the IL.
The Customer class here offers only a single constructor, which takes a string argument representing
an instance’s name. It sets its id field based on the static idCounter and then stores the name argument
value in its instance name field. The class implements an implicit invariant that fully initialized customers
have a nonzero id and a non-null name.
|

