Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference on initializing object inside class declaration v/s constructor

I was going through object initialization and constructor initialization for my object, but couldn't get exact reply to my question. What is the difference between Case1 and Case2 here;

Case 1:

namespace ConsoleApplication2
{
    class MyBuilder
    {
        private MySynchronizer m_synchronizer = new MySynchronizer();

        public MyBuilder()
        {

        }

        public void ProcessRecord(int recordNumber)
        {
            m_synchronizer.Process(recordNumber);
        }
    }
}

Case II:

namespace ConsoleApplication2
{
    class MyBuilder
    {
        private MySynchronizer m_synchronizer;

        public MyBuilder()
        {
          m_synchronizer = new MySynchronizer();

        }

        public void ProcessRecord(int recordNumber)
        {
            m_synchronizer.Process(recordNumber);
        }
    }
}

This is sample code to show how I am calling my Builder class;

 class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Press any key to stop");
            MyBuilder builder = new MyBuilder();
            builder.ProcessRecord(2);
        }
    }

[Sorry, if I could not have rephrase the question properly, in which case anyone can provide the link to other SO article]

like image 617
OmGanesh Avatar asked Oct 15 '25 14:10

OmGanesh


2 Answers

The difference here is really subtle, and can only easily be appreciated in IL:

class MyBuilder1
{
    private MySynchronizer m_synchronizer = new MySynchronizer();

    public MyBuilder1()
    {

    }
}

gives us the constructor:

.method public hidebysig specialname rtspecialname 
    instance void .ctor () cil managed 
{
    // Method begins at RVA 0x2050
    // Code size 18 (0x12)
    .maxstack 8

    IL_0000: ldarg.0
    IL_0001: newobj instance void MySynchronizer::.ctor()
    IL_0006: stfld class MySynchronizer MyBuilder1::m_synchronizer
    IL_000b: ldarg.0
    IL_000c: call instance void [mscorlib]System.Object::.ctor()
    IL_0011: ret
} // end of method MyBuilder1::.ctor

where-as this:

class MyBuilder2
{
    private MySynchronizer m_synchronizer;

    public MyBuilder2()
    {
      m_synchronizer = new MySynchronizer();

    }
}

gives us:

// Methods
.method public hidebysig specialname rtspecialname 
    instance void .ctor () cil managed 
{
    // Method begins at RVA 0x2063
    // Code size 18 (0x12)
    .maxstack 8

    IL_0000: ldarg.0
    IL_0001: call instance void [mscorlib]System.Object::.ctor()
    IL_0006: ldarg.0
    IL_0007: newobj instance void MySynchronizer::.ctor()
    IL_000c: stfld class MySynchronizer MyBuilder2::m_synchronizer
    IL_0011: ret
} // end of method MyBuilder2::.ctor

The difference is simply one of ordering:

  • field initializers (MyBuilder1) happen before the base-type constructor call (object is the base here; call instance void [mscorlib]System.Object::.ctor() is the base-constructor call)
  • constructors happen after the base-type constructor call

In most cases, this won't matter. Unless your base-constructor invokes a virtual method that the derived type overrides: then whether or not the field has a value in the overridden method will be different between the two.

like image 96
Marc Gravell Avatar answered Oct 17 '25 04:10

Marc Gravell


As @Marc already mentioned, the difference is in the order of the base constructor.

I have added the base constructor

 class Base
    {
        public Base()
        {
            Console.WriteLine("Inside Base constructor");
        }
    }

and modified my class "MyBuilder" to derived from it as;

 class MyBuilder : Base
    {

    }

Now, the output from case1 looks like:

enter image description here

whereas from case2:

enter image description here

Hence,

  • If you have multiple constructor, then the case1 approach might be better, since there is less error prone as someone could easily add another constructor and forget to chain it.
  • If you have single constructor and no any logic flow that depends on base constructor order, then the case2 seems better, as that will make the code cleaner. [no offence, personal preference]
like image 23
OmGanesh Avatar answered Oct 17 '25 04:10

OmGanesh



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!