tags:

views:

636

answers:

12

I found a while ago (and I want to confirm again) that if you declare a class level variable, you should not call its constructor until the class constructor or load has been called. The reason was performance - but are there other reasons to do or not do this? Are there exceptions to this rule?

ie: this is what I do based on what I think the best practice is:

public class SomeClass
{
   private PersonObject _person;

   public SomeClass()
   {
      _person = new PersonObject("Smitface");
   }
}

opposed to:

public class SomeClass
{
   private PersonObject _person = new PersonObject("Smitface");

   public SomeClass()
   {

   }
}
A: 

I prefer the latter, but only becuase I find it neater.

It's personal preference really, they both do the same thing.

jonnii
+6  A: 

Honestly, if you look at the IL, all that happens in the second case is the compiler moves the initialization to the constructor for you.

Personally, I like to see all initialization done in the constructor. If I'm working on a throwaway prototype project, I don't mind having the initialization and declaration in the same spot, but for my "I want to keep this" projects I do it all in the constructor.

OwenP
A: 

I prefer to initialize variables as soon as possible, since it avoids (some) null errors.

Edit: Obviously in this simplified example there is no difference, however in the general case I believe it is good practice to initialize class variables when they are declared, if possible. This makes it impossible to refer to the variable before it it initialized, which eliminates some errors which would be possible when you initialize fields in the constructor.

As you get more class variables and the initialization sequence in the constructor gets more complex, it gets easier to introduce bugs where one initialization depends on another initialization which haven't happend yet.

JacquesB
Your comment doesn't really apply here. The variables are being initialized at the same time regardless of which method is used.
Herms
The commenter's edited comment has a good point--if I have a field with an initializer, I KNOW it will be initialized. If I have a field in a class with 20 constructors, it's harder to make sure the variable is initialized before it is ever used. The Eric Lippert post makes this even more true.
Neil Whitaker
+1  A: 

It depends on the context of how the variable will be used. Naturally constants and static or readonly should be initialized on declaration, otherwise they typically should be initialized in the constructor. That way you can swap out design patterns for how your objects are instatiated fairly easy without having to worry about when the variables will be initialized.

Marcus King
you could never make assumptions looking at the constructor alone because the language allows you to do it another way. what if you import some code you wrote last year the other way? hope you don't switch patterns. (in this case it seems the generated IL is equivalent, but there could be other)
Dustin Getz
A: 

The first declaration is actually cleaner. The second conceals the fact the constructor initializes the class in the static constructor. If for any reason the constructor fails, the whole type is unusable for the rest of the applicaiton.

Nescio
Static constructor? I don't see anything static in this example.
Neil Whitaker
+11  A: 

If you set your variable outside of the constructor then there is no error handling (handeling) available. While in your example it makes no difference, but there are many cases that you may want to have some sort of error handling. In that case using your first option would be correct.

Nescio talked about what implication this would have on your applicaiton if there were some constructor failures.

For that reason, I always use Option #1.

discorax
The fact that a constructor can fail and you can't handle the error in #2 is a really good reason to use #1: In this case it's not about style but reliability.
Jared Updike
Good reason for choosing the first style.
Esteban Brenes
your spelling of "handleing" reminded me of the "chronicles of george" and his spelling of "havening". +1 for the memory.
StingyJack
http://chroniclesofgeorge.nanc.com/tickets13.htm
StingyJack
I believe initializing your members variables inside the constructor is subject to race conditions when threading is used, while initializing at declaration is ran as atomic operation.
Haoest
A: 

I like to initialize in the constructor because that way it all happens in one place, and also because it makes it easier if you decide to create an overloaded constructor later on.

Also, it helps to remind me of things that I'll want to clean up in a deconstructor.

chills42
A: 

the latter can take advantage of lazy instantiation, i.e. it won't initialize the variable until it is referenced

Steven A. Lowe
A: 

i think this type of question is stylistic only, so who cares what way you do it. the language allows both, so other people are going to do both. don't make bad assumptions.

Dustin Getz
+4  A: 

Actually, in spite of what others have said, it can be important whether your initialization is inside or outside the constructor, as there is different behaviour during object construction if the object is in a hierarchy (i.e. the order in which things get run is different).

See this post and this post from Eric Lippert which explains the semantic difference between the two in more detail.

So the answer is that in the majority of cases it doesn't make any difference, and it certainly doesn't make any difference in terms of performance, but in a minority of cases it could make a difference, and you should know why, and make a decision based on that.

Greg Beech
+1  A: 

You should generally prefer the second variant. It's more robust to changes in your code. Suppose you add a constructor. Now you have to remember to initialize your variables there as well, unless you use the second variant.

Of course, this only counts if there are no compelling reasons to use in-constructor initialization (as mentioned by discorax).

Konrad Rudolph
+1  A: 

There's a common pattern called Dependency Injection or Inversion of Control (IOC) that offers exactly these two mechanisms for "injecting" a dependant object (like a DAL class) into a class that's furthur up the dependency chain (furthur from the database)

In this pattern, using a ctor, you would

public class SomeClass
{
private PersonObject per;

 public SomeClass(PersonObject person) 

 {      
     per = person;   
 }

}

private PersonObject Joe = new PersonObject("Smitface");

SomeClass MyObj = new SomeClass(Joe);

Now you could for example, pass in a real DAL class for production call or a test DAL class in a unit test method...

charles bretana