Instance Constructors

Instance Constructors

Instance constructors, unlike class constructors, are specific to an instance of a type and are used to initialize both static and instance fields of the type. Functionally, instance constructors in IL are a direct analog of C++ constructors. Instance constructors can have parameters but must return void, must be instance, must have specialname and rtspecialname flags, and have the name .ctor, which is also an ILAsm keyword. Like class constructors, instance constructors cannot use the vararg calling convention. In the first release of the common language runtime, instance constructors are not allowed to be virtual. A type can have multiple instance constructors, but they must have different parameter lists because the name (.ctor) and the return type (void) are fixed.

Usually, instance constructors are called during the execution of the newobj instruction, when a new type instance is created:

.class public Foo {    .field private int32 tally    .method public void .ctorint32 tally_init)    {       ldarg.0 // Load the instance reference       ldarg.1 // Load the initializing value       stfld int32 Foo::tally // This->tally = tally_init;       ret   }     } .method public static void Exec( ) {    .locals init (class Foo foo)     // Foo is a reference but not an instance    ldc.i4   128 // Put 128 on stack as Foo's constructor argument    newobj instance void Foo::.ctor(int32)     // Instance of Foo is created    stloc.0 // foo = new Foo(128);     }

But, as is the case for class constructors, an instance constructor can be called explicitly. Calling the instance constructor resets the fields of the type instance and does not create a new instance. The only problem with calling class or instance constructors explicitly is that sometimes the constructors include type instantiations, if some of the fields to be initialized are of object reference type. In this case, additional care should be taken to avoid multiple type instantiations.

warning

Calling the class and instance constructors explicitly, however possible in principle, renders the code unverifiable. This limitation is imposed on the constructors of the reference types (classes) only and does not concern those of the value types. The only place where an instance constructor of a class can be called explicitly is within an instance constructor of the class’s direct descendant.

Constructors of the classes cannot be the arguments of the ldftn instruction. In other words, you can’t obtain a function pointer to a .ctor or .cctor of a class.

I repeat: all these limitations can be bypassed only if your code is run from the local drive with verification disabled. Constructors of the value types are not subject to these limitations.

Class and instance constructors are the only methods allowed to set the values of the fields marked initonly. If an initonly field is initialized by the .cctor of the current type, it can subsequently be modified by a .ctor of this type but not by any other method. Methods belonging to some other class, including .ctor and .cctor, cannot modify the initonly field, even if the field accessibility permits. Subsequent explicit calls to .ctor and .cctor can modify the initonly fields as well as the first, implicit initializing calls.

Because value types are not instantiated using the newobj instruction, instance constructors make less sense for them. If an instance constructor is specified for a value type, it should be called explicitly by using the call instruction, even though declaring a variable of a value type creates an instance of this value type. Interfaces cannot have instance constructors at all; there is no such thing as an interface instance.



Inside Microsoft. NET IL Assembler
Inside Microsoft .NET IL Assembler
ISBN: 0735615470
EAN: 2147483647
Year: 2005
Pages: 147
Authors: SERGE LIDIN

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net