Search code examples
c#constructorobject-initializers

Regarding System.Object Constructor class in c#


Object class constructor is called in the constructor of the class when an object is created . What happens in the Object Constructor?


Solution

  • In the Reference Source for object, this is the code for the constructor:

    // Creates a new instance of an Object.
    [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
    [System.Runtime.Versioning.NonVersionable]
    public Object()
    {            
    }
    

    Nothing happens there.

    In the comments you ask how the class members are initialized to their default value. The Main() method in the following program...

    namespace ConsoleApp1
    {
        class Program
        {
            static void Main(string[] args)
            {
                Program program = new Program();
            }
        }
    }
    

    is translated by the compiler to the following MSIL:

    IL_0000:  nop
    IL_0001:  newobj     instance void ConsoleApp1.Program::.ctor()
    IL_0006:  stloc.0
    IL_0007:  ret
    

    The interesting instruction here is newobj. Which among other things:

    allocates a new instance of the class associated with ctor and initializes all the fields in the new instance to 0 (of the proper type) or null references as appropriate.

    So newobj initializes all class members to some type of 0 or to null.

    In the comments you ask what happens if you initialize a field to a specific value. If we modify the program above:

    namespace ConsoleApp1
    {
        class Program
        {
            private int i = 1;
    
            public Program()
            {
                i = 2;
            }
    
            static void Main(string[] args)
            {
                Program program = new Program();
            }
        }
    }
    

    We have added a field i that is initialized to 1 and a constructor that sets i to 2.

    The MSIL for the constructor of the Program class looks like this:

    IL_0000:  ldarg.0
    IL_0001:  ldc.i4.1
    IL_0002:  stfld      int32 ConsoleApp1.Program::i
    IL_0007:  ldarg.0
    IL_0008:  call       instance void [mscorlib]System.Object::.ctor()
    IL_000d:  nop
    IL_000e:  nop
    IL_000f:  ldarg.0
    IL_0010:  ldc.i4.2
    IL_0011:  stfld      int32 ConsoleApp1.Program::i
    IL_0016:  ret
    

    So now,

    • newobj creates the object and initializes it's memory (setting i to 0).
    • The constructor of Program runs and ldc.i4.1 followed by stfld ... i sets i to 1.
    • Then the constructor of the base class System.Object is called.
    • And then (still in the constructor of Program) i is set to 2 (ldc.i4.2 followed by stfld ... i).

    So effectively i is set 3 times (to 0, 1, and 2) and when the constructor of the base class runs i has a different value then when the constructor of Program finishes.

    For the order in which initializers and constructors run see these posts by Eric Lippert.