Search code examples
c#default-constructor

How fields are initialized when not provide a constructor by yourself?


//CodeSample1
//declare class fileds but not initialize them.
public class Cat
{
    public int Age;
    public string Name;
}

Cat aCat = new Cat();

Check the result, aCat.Age is 0, aCat.Name is null.

How the fields are initialized? The above code just declare fields and not initialize them.

If you do not provide a constructor for your object, C# will create one by default that instantiates the object and sets member variables to the default values as listed in Default Values Table.(From Microsoft document 1)

So it's the compiler generated default constructor initialize fields. Is it right?

Changed Code, initialize fields when declare them.

//CodeSample2
//declare class fields and initialize them at same time.
public class Cat
{
    public int Age = 4;
    public string Name = "Black";
}

Cat aCat = new Cat();

This time the Result is that aCat.Age is 4, and aCat.Name is "Black".

I know the result is as expected. But do not understand how it works.

Fields are initialized immediately before the constructor for the object instance is called. (From Microsoft Document 2)

Combine the Microsoft document 1 and Microsoft Document 2, CodeSample1 and CodeSample2 should have the same results (I know it strange).

My understanding is, in CodeSample2, firstly Age field is initialize to 4, then the compiler generated default constructor is called and set the age to default value (0).

Have I misunderstood the documents, or the documents are somewhat wrong?

If there are more accurate documents, please show me.


Solution

  • You're using the C# Programming Guide. Unfortunately, at times it attempts to simplify things and in this case, I'd say that the simplification's it has made have led to a mistake in the documentation.

    If we, instead, consult the C# language specification (currently, version 5 is the latest available. A draft for 6 can be found on Github), we get the more authoritative version. First, let's look at Default Constructors, in section 10.11.4:

    If a class contains no instance constructor declarations, a default instance constructor is automatically provided. That default constructor simply invokes the parameterless constructor of the direct base class. If the class is abstract then the declared accessibility for the default constructor is protected. Otherwise, the declared accessibility for the default constructor is public. Thus, the default constructor is always of the form

    protected C(): base() {}
    

    or

    public C(): base() {}
    

    So, as we can already see - no claims here about initializing the fields. Now, let's go look at section 10.5.4, Field Initialization:

    The initial value of a field, whether it be a static field or an instance field, is the default value (§5.2) of the field’s type. It is not possible to observe the value of a field before this default initialization has occurred, and a field is thus never “uninitialized”.

    Okay, so fields are always initialized with their default values for their type, whatever happens. And this always happens first. Finally, 10.5.5, Variable Initialization says this:

    The default value initialization described in §10.5.4 occurs for all fields, including fields that have variable initializers... when an instance of a class is created, all instance fields in that instance are first initialized to their default values, and then the instance field initializers are executed in textual order.

    and:

    The instance field variable initializers of a class correspond to a sequence of assignments that are executed immediately upon entry to any one of the instance constructors (§10.11.1) of that class