12

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

We are arguing about coding practices. The examples here are a little 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.

Cœur
  • 37,241
  • 25
  • 195
  • 267
John Nicholas
  • 4,778
  • 4
  • 31
  • 50
  • possible duplicate of [Best Practice: Initialize class fields in constructor or at declaration?](http://stackoverflow.com/questions/24551/best-practice-initialize-class-fields-in-constructor-or-at-declaration) – Robert Harvey May 10 '10 at 14:46
  • 1
    it is but i don't find the answers in that thread to be compelling - the first is a little dogmatic. The reference to FXCop is a strong argument, as is the maintenance and constructor chaining argument but aside from that nothing too factual. – John Nicholas May 10 '10 at 14:52
  • 3
    For some interesting consequences of the subtle differences between initializing in the field and in the body, see http://blogs.msdn.com/ericlippert/archive/2008/02/15/why-do-initializers-run-in-the-opposite-order-as-constructors-part-one.aspx and http://blogs.msdn.com/ericlippert/archive/2008/02/18/why-do-initializers-run-in-the-opposite-order-as-constructors-part-two.aspx – Eric Lippert May 10 '10 at 16:08
  • Great links, thanks - I had stumbled upon them earlier today. Should of though to post them. Glad you did :D – John Nicholas May 10 '10 at 17:22

10 Answers10

19

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
  • 380,855
  • 102
  • 628
  • 825
  • 1
    i wished i could upvote you more than once. ;-) – Oliver May 10 '10 at 15:00
  • 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 May 10 '10 at 15:15
14

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.

kemiller2002
  • 113,795
  • 27
  • 197
  • 251
2

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.

Community
  • 1
  • 1
Jesse C. Slicer
  • 19,901
  • 3
  • 68
  • 87
  • Why does FxCop make this recommendation? – Robert Harvey May 10 '10 at 14:45
  • @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 May 10 '10 at 14:47
  • 2
    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 May 10 '10 at 14:53
  • Even if FxCop recommends it, i would prefer using constructor chains like `public MyClass() : MyClass(String.Empty)` – Oliver May 10 '10 at 14:59
  • 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 May 10 '10 at 15:06
1

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
  • 16,498
  • 6
  • 59
  • 85
1

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;
        ...
    }
} 
mohdajami
  • 9,604
  • 3
  • 32
  • 53
  • 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 May 10 '10 at 15:01
  • 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. – mohdajami May 10 '10 at 18:02
1

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
  • 17,883
  • 5
  • 53
  • 72
1

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

quillbreaker
  • 6,119
  • 3
  • 29
  • 47
  • 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 May 10 '10 at 15:00
  • 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 May 10 '10 at 17:48
  • 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 May 10 '10 at 17:52
  • One might wonder why one is hardcoding literal strings into your application in the first place. – quillbreaker May 10 '10 at 19:02
  • 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 May 11 '10 at 13:29
  • 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 May 12 '10 at 13:50
  • I'm not sure what you're getting at. – quillbreaker May 12 '10 at 20:07
0

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
  • 242,243
  • 40
  • 408
  • 536
0

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
  • 117,338
  • 33
  • 229
  • 351
0

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
  • 21,601
  • 5
  • 62
  • 79