Inline Initialization

I must admit that I was rather surprised when I learnt that inline initialization translates into the default constructor-based initialization in the IL. So, for example, these two pieces of code are equivalent:

    sealed internal class Inline
    {
        private int x = 5;
    }


is the same as

    sealed internal class Inline
    {
        public Inline()
        {
            x = 5;
        }

        private int x;
    }

The above can be verified by examining the IL of the first example through the ILDASM. Below I am showing the snapshot of what the IL code in .ctor generated by the IL looks like:

InLineIL

As pointed out in ([1], chapter 8), this means that non-constant fields initialized inline lead to the IL code explosion.

In one of my previous posts on C# language features I wrote that parameter-less constructors are not allowed in value types before C# 6.0. This is the reason why inline initialization is illegal in structs. For example, the following won’t compile:

    struct NoInline
    {
        int a = 5;
    }

If you examine the IL for the struct, you will see that it has no code for the default .ctor. The implicit parameter-less constructor is intrinsic to the struct (i.e. it is provided by the C# language implementation) and cannot be modified. Thus, for C# struct, there is no way to translate the inline initializers into the initialization inside the parameter-less constructor.

The story is very different for static fields. In value types, static fields can be initialized inline. As you may have already guessed, such initialization does translate into the parameter-less static constructor initialization. For example, these two pieces of code are equivalent in the IL:

struct NoInline
{
        static int a = 5;
}

is the same as

struct NoInline
{
    static NoInline()
    {
        a = 5;
    }

        static int a;
}

References:
[1] J.Richter. CLR via C#, 4th edition. 2014.

Advertisements
This entry was posted in C# Programming and tagged . Bookmark the permalink.

5 Responses to Inline Initialization

    • Or to go in another direction, have a look at the fun that happens with static type initializers vs static constructors http://csharpindepth.com/Articles/General/Beforefieldinit.aspx

      Like

    • Elena says:

      Aha! This is indeed a very good point, and goes beyond my naive “discovery” about inline initializers becoming a part of the class’s default constructor.

      Thanks for pointing me to Eric’s article which is about the order of field initialization and constructor calls, as well as the reason for why C# behaves like it does, especially with the readonly fields.

      Now that I know that inline initialization becomes a part of the default constructor’s code, it is important to highlight, as you suggest, that the order in which that field initialization and the native constructor’s instructions happen is something to be aware of. That is, the fields are initialized before anything else.

      I guess this may be a good description for how the code in Eric’s article is executed:

      1. The readonly derivedFoo initialization becomes part of Derived constructor, and executes first via a call to Foo’s constructor. The 1st line of output is: “Foo constructor: Derived initializer”.
      2. Since Derived class is a subclass of Base, the Base’s constructor is called next. Here we have that Base class baseFoo initialization is a part of Base’s constructor! Thus, Foo’s constructor is called again. The 2nd line of output is: “Foo constructor: Base initializer”.
      3. Base class constructor continue’s with the rest of its instructions. The 3rd line of output therefore is: “Base constructor”.
      4. Finally, the rest of the Derived class constructor’s code is executed. We have the last line of output: “Derived constructor”.

      Like

  1. Elena says:

    Thank you, GrahamTheCoder for this suggestion!

    If the Inline sub-class has inline field initializers, then these become part of the sub-class constructor. Also, as the case with the Inline class, the constructor of the parent class is called. For Inline sub-class the parent is Inline, so, its default constructor is called again.

    Like

  2. If you haven’t already, have a look at what happens when you have a subclass of Inline with a field initializer too, it is perfectly sensible but goes against some people’s intuition.

    Like

Comments are closed.