views:

344

answers:

10

Possible Duplicate:
Best Practice: Initialize class fields in constructor or at declaration?

So its monday and we are arguing about coding practises. The examples here are a litttle too simple, but the real deal has several constructors. In order to initialise the simple values (eg dates to their min value) I have moved the code out of the constructors and into the field definitions.

public class ConstructorExample
{
    string _string = "John";

}

public class ConstructorExample2
{
    string _string;

    public ConstructorExample2()
    {
        _string = "John";
    }
}

How should it be done by the book? I tend to be very case by case and so am maybe a little lax about this kind of thing. However i feel that occams razor tells me to move the initialisation out of multiple constructors. Of course, I could always move this shared initialisation into a private method.

The question is essentially ... is initialising fields where they are defined as opposed to the constructor bad in any way?

The argument I am facing is one of error handling, but i do not feel it is relevant as there are no possible exceptions that won't be picked up at compile time.

A: 

I prefer to initialize simple fields like that outside of the constructor.

It shouldn't cause any issues since compilation actually moves those initializations into the constructor at compile-time anyway.

Justin Niessner
+2  A: 

Microsoft FxCop by default recommends field initializers over using the constructor. This question is also a duplicate of this one and should provide some insight.

With static classes, you'll have to note some subtleties as addressed at this question.

Jesse C. Slicer
Why does FxCop make this recommendation?
Robert Harvey
@Robert: glad you asked. I updated my response to include some supporting documentation in the form of other SO questions/answers. My take on it is that the field initializers execute before constructors and it gives the constructors a "more ready" object to work with.
Jesse C. Slicer
My mistake - seems like FxCop only recommends this in the case of static classes: http://msdn.microsoft.com/en-us/library/ms182275.aspx
Jesse C. Slicer
Even if FxCop recommends it, i would prefer using constructor chains like `public MyClass() : MyClass(String.Empty)`
Oliver
While true, it (constructor chaining) is another small chunk of logic that needs to be written right the first time and then maintained. The in-line method is pretty much set it and forget it.
Jesse C. Slicer
+9  A: 

It's not necessarily bad to initialize values outside of the constructor, and the problem you have here:

 string _string;

    public ConstructorExample2()
    {
        _string = "John";
    }

Is that if you have multiple constructors you have to remember to either
1. Reinitialize _string in every constructor
2. Separate the logic out into a common method and call that method in every constructor
3. Call the constructor with the logic in it, from the other constructors. (Chain the constructors)
Now this isn't necessarily a problem, but you have to remember to do it. By initializing it outside of the constructor, it's done for you. It's one less thing you need to remember to do.

Kevin
You don't need to reinitialize the _string in every constructor. Instead you can chain ctors by using a `public MyClass() : this(String.Empty)`
Oliver
With the comment, I quite like this as a balanced answer.
John Nicholas
Oliver care to provide some reasoning?
John Nicholas
A: 

If the initialization of the variable will be the same, no matter what arguments are passed to the constructor, then it doesn't make sense to clutter the constructor method with the unnecessary initialization code. In this case, I initialize in-place.

spender
A: 

Inisialing the fields in the constructor is better. This way if/when a different constructor is added you know that all the fields are starting with null/default values and you can initialise them appropriately.

Ben Robinson
+1  A: 

In the above example the assignment of "John" to _string has no logical reliance on any variables and therefore it should be outside of the constructor in the field initializer.

So long as it is not possible to initialize the object in an non-usable state then it doesn't matter.

When the code is compiled both approaches will be the same anyway.

David Neale
+11  A: 

Note that all such field declaration-level initialization will be performed once for each constructor-chain, even if the constructor by itself sets the field to something else.

If you chain constructors together, the fields will be initialized in the common, first, constructor that is called.

Look at this example:

using System;

namespace ClassLibrary3
{
    public class Class1
    {
        private string _Name = "Lasse";

        public Class1()
        {
        }

        public Class1(int i)
            : this()
        {
        }

        public Class1(bool b)
        {
            _Name = "Test";
        }
    }
}

This code compiles as this:

using System;

namespace ClassLibrary3
{
    public class Class1
    {
        private string _Name;

        public Class1()
        {
            _Name = "Lasse"
        }

        public Class1(int i)
            : this()
        {
            // not here, as this() takes care of it
        }

        public Class1(bool b)
        {
            _Name = "Lasse"
            _Name = "Test";
        }
    }
}
Lasse V. Karlsen
i wished i could upvote you more than once. ;-)
Oliver
Yeah, Sorry I couldn't mark this as the answer. The point about initialisers being called in what order initially felt to me as being counter intuitive is fairly strong - esp in inheritance scenarios adn knowing what has and has not been initialised.
John Nicholas
A: 

Not sure about C#, but in Java source code they seem to prefer the constructor, example:

public class String{
    char[] value;
    int offset;
    ...
    public String(){
        value = new char[0];
        offset = 0;
        ...
    }
} 
medopal
I am arguing with a c / Java programmer ;) There is a way to initialise like this in java http://java.sun.com/docs/books/tutorial/java/javaOO/initial.html
John Nicholas
I know there is, but this snippet is from Java source code itself. Usually when I suspect something I check how the great minds who wrote Java solved it.
medopal
+1  A: 

I think for simple initializations like that it's fine to do it in the declaration. However, I don't understand the error handling argument. Even if there is an exception in the initialization, I think you will find that your normal error handling mechanism will work the same. It will still throw an exception when you call the constructor.

tster
I tend to agree, but don't want to dismiss it out of hand.
John Nicholas
+1  A: 

I tend to initialize things in the get accessor, where they are first used. If null then initialize and all that.

quillbreaker
I hadn't considered that option. The only problem is in the case when a null value is a valid value, but is not the default value.
John Nicholas
You could always do a boolean to indicate initialized state instead of relying on "if (value==null) {initialize;}". I like initialization upon access - I think it's more frequently called "lazy initialization". It's very handy when working with a database. It also makes it easy to cache things if you are of a mind to.
quillbreaker
I don't think I would ever take this approach for a literal value initializer (like a literal string). It trades a one-time assignment with a test for null on every get, and makes the code more complex. For other scenerios, particularly with large or slow object initializations, this might make sense.
Jeffrey L Whitledge
One might wonder why one is hardcoding literal strings into your application in the first place.
quillbreaker
I assume you are trolling.
John Nicholas
Not really. There are lots of good reasons to minimize the number of hardcoded strings you have in your application, to at least move them to a configuration file.
quillbreaker
I suggest you look harder, there are far more perlplexing things with the classes I gave you. They are named badly, there is no way to access the data and there are no methods on the classes ... they do nothing except take up memory. I really don't see what benefit a config file would be in this case tbh - in fact it would turn your problem with my code into a far bigger one as now not only do the classes do nothing they also place redundant requirements on the config files.
John Nicholas
I'm not sure what you're getting at.
quillbreaker