3

Possible Duplicate:
C# member variable initialization; best practice?
Why should member variables be initialized in constructors?
Should I initialize variable within constructor or outside constructor

In Java/C# usually we see

public class MyClass {
    private MyObject myObject;

    public MyClass(){
        myObject = new MyObject();
    }
}

instead of

public class MyClass {
    private MyObject myObject = new MyObject();

    public MyClass(){

    }
}

What is the reason if any?

Community
  • 1
  • 1
Kenoyer130
  • 6,874
  • 9
  • 51
  • 73
  • 1
    Use the resources only when needed. – Andre Calil Aug 28 '12 at 17:30
  • 3
    `In Java/C# usually we see`. That's quite an assumption. I use the second approach whenever possible over the first. It's probably just the style of programming used by those you're working with. – Servy Aug 28 '12 at 17:31
  • 1
    @AndreCalil in this case, the object won't be created until the constructor is called. Basically, both codes will work in the same way. – Luiggi Mendoza Aug 28 '12 at 17:31
  • Interestingly... some serializers do not actually invoke the constructor when deserializing an object. – Eric J. Aug 28 '12 at 17:32
  • @LuiggiMendoza That's kinda new for me. Could you kindly provide any reference about it? Thanks. – Andre Calil Aug 28 '12 at 17:33
  • 3
    @AndreCalil look [here](http://www.csharp411.com/c-object-initialization/), the sample will behave similar for Java code. The only way the first code could use resources it would be if the property has the `static` modifier. – Luiggi Mendoza Aug 28 '12 at 17:35
  • 1
    I for one would prefer the second one. – CodesInChaos Aug 28 '12 at 17:37
  • As stated in the answer of the possible duplicate: "if the initialization value is different in different constructors (or even calculated in the constructor), you must do it in the constructor". I guess this resume the answer. – Luiggi Mendoza Aug 28 '12 at 17:39

2 Answers2

1

There is no difference, it's just a style choice.

In your example, if you choose the second approach you don't have to provide a constructor, which saves you a few lines of code.

Keppil
  • 45,603
  • 8
  • 97
  • 119
  • You may still need a constructor – JonH Aug 28 '12 at 17:35
  • There are minor differences (as opposed to **no** differences), in certain edge cases. They are mostly the same, although each can be beneficial at times. – Servy Aug 28 '12 at 17:35
  • 1
    @Servy, could you provide some examples or direction on the "certain edge cases"? Especially how they are different. To me, they seem the same only probably slightly easier to maintain. I'm really interested in this answer. – Brad Boyce Aug 28 '12 at 17:38
  • 1
    @BradBoyce Call to the base constructor is one example. I believe initializers run before the base constructor is called, the constructor afterwards. – CodesInChaos Aug 28 '12 at 17:43
1

This boils down to coding preference as stated in one of the comments. If you compile the following code

public class TestInitialization
{
    private object test1 = new object();
    private object test2;

    public TestInitialization()
    {
        this.test2 = new object();
    }
}

When compiled, the actual code used is as follows

public class TestInitialization
{
    private object test1;
    private object test2;

    public TestInitialization()
    {
        this.test1 = new object();
        this.test2 = new object();
    }
}

So they are exactly the same thing, use whichever you prefer.

EDIT: Here is an example of a base class with an inherited class and the resultant compiled IL.

Base class

class basetest
{
    private object test1 = new object();
    private object test2;

    public basetest()
    {
        this.test2 = new object();
    }
}

Inherited class

class testclass : basetest
{
    private object testclass1 = new object();
    private object testclass2;

    public testclass() : base()
    {
        this.testclass2 = new object();
    }
}

Resulting IL Base class

.class private auto ansi beforefieldinit basetest
    extends [mscorlib]System.Object
{
    .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
    {
        .maxstack 8
        L_0000: ldarg.0 
        L_0001: newobj instance void [mscorlib]System.Object::.ctor()
        L_0006: stfld object logtest.basetest::test1
        L_000b: ldarg.0 
        L_000c: call instance void [mscorlib]System.Object::.ctor()
        L_0011: nop 
        L_0012: nop 
        L_0013: ldarg.0 
        L_0014: newobj instance void [mscorlib]System.Object::.ctor()
        L_0019: stfld object logtest.basetest::test2
        L_001e: nop 
        L_001f: ret 
    }


    .field private object test1

    .field private object test2

}

Inherited class IL

.class private auto ansi beforefieldinit testclass
    extends logtest.basetest
{
    .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
    {
        .maxstack 8
        L_0000: ldarg.0 
        L_0001: newobj instance void [mscorlib]System.Object::.ctor()
        L_0006: stfld object logtest.testclass::testclass1
        L_000b: ldarg.0 
        L_000c: call instance void logtest.basetest::.ctor()
        L_0011: nop 
        L_0012: nop 
        L_0013: ldarg.0 
        L_0014: newobj instance void [mscorlib]System.Object::.ctor()
        L_0019: stfld object logtest.testclass::testclass2
        L_001e: nop 
        L_001f: ret 
    }


    .field private object testclass1

    .field private object testclass2

}

I think there's a bit of confusing on my part. In this example the initializer outside of the constructor is initialized FIRST just before the base constructor is called. So no matter what, initializers outside of a constructor will be initialized first before the ones inside a constructor and for the most part this shouldn't matter. Technically they all get converted to be intialized inside a constructor and the following rules apply.

  1. All initializers outside of a constructor are run first
  2. All base class constructors are called
  3. All initializers inside constructor are run

Basically the compiler prepends all initializers outside the constructor to the constructor code and then runs as normal.

So this

public class test : basetest
{
    private object test1 = new object();
    private object test2;

    public test() : base()
    {
        this.test2 = new object();
    }
}

public class basetest
{
    private object basetest1 = new object();
    private object basetest2;

    public basetest()
    {
        this.basetest2 = new object();
    }
}

becomes

public class test : basetest
{
    private object test1;
    private object test2;

    public test()
    {
        //prepend everything first
        this.test1 = new object();

        //call base
        base(); //not legal but just an example

        //everything else that was already here
        this.test2 = new object();
    }
}

public class basetest
{
    private object basetest1;
    private object basetest2;

    public basetest()
    {
        //prepend initializers
        this.basetest1 = new object();

        //if there were more base classes, the constructors would be called here

        //do everything else that was already here
        this.basetest2 = new object();
    }
}

Hopefully that makes more sense and clears some things up. I know I was having an issue understand what some people were meaning when they said it runs "first" or "outside" of the constructor; it does in fact ALL run INSIDE a constructor but the order of what is called is affected.

vane
  • 2,125
  • 1
  • 21
  • 40
  • Well, it's not *exactly* the same. It's *almost* exactly the same. None of the important edge cases seems to apply to this example though. – Servy Aug 28 '12 at 17:38
  • @Servy Could you provide an example edge case so I understand what you mean? I've tested quite a few examples compiled with VS2010 and checked with Reflector going all the way down to IL and they all end up the same; even static variables get initialized in the constructor.. albeit a special static constructor called .cctor instead of .ctor but in a constructor nonetheless. I might be missing something. – vane Aug 28 '12 at 18:56
  • 1
    [see other comment](http://stackoverflow.com/questions/12164474/why-is-object-initialization-preferred-in-the-constructor/12164571#comment16280334_12164545) `initializers run before the base constructor is called, the constructor afterwards.` I wrote up a quick example to verify that it is indeed the case. – Servy Aug 28 '12 at 19:02
  • @BradBoyce not sure how I can comment on the other answer so I'm doing it here. I've tested inheritance and initializers in regards to constructors. In my tests on VS2010 EVERYTHING (initializers) are put inside .ctor and .cctor which are constructors so I've yet to see an example where this is not the case. The order in which the variables are initialized inside the constructor might be affected by having them outside the constructor and inside the constructor but they all get initialized inside .ctor and .cctor – vane Aug 28 '12 at 19:06
  • @Servy I also just ran an example of a base class with a constructor, an inherited class with a constructor and both with initializers outside of the constructor... the initializers where placed inside .ctor once compiled, so I still don't see a difference. – vane Aug 28 '12 at 19:07
  • I can't really dump the code into a comment here...Just have a base class that prints a value in the constructor, a separate class that prints something in it's constructor, and then have the child class initialize the separate class in the manor descried in the OP. The printouts will happen in a different order. – Servy Aug 28 '12 at 19:10
  • @Servy See the edit I just made, I think it will clarify what we've both been saying and show that you are indeed right that in this example the order is affected. – vane Aug 28 '12 at 19:25
  • Not exactly succinct, but it seems we are now understand each other. Your final "transformation" seems to be correct. – Servy Aug 28 '12 at 19:26