tags:

views:

107

answers:

9

I'm just curious, are there any diferences between this two ways of field initialization ? When to use wich one ?

Fist way

public class Class1
{
   private SomeClass someclass;

   public Class1()
   {
       someclass = new SomeClass(some arg);
   }
}

Second way

public class Class1
{
   private SomeClass someclass = new SomeClass(some arg);

}

The field in the second example could be readonly.

A: 

The constructor way is recommended, because of exceptions management and debug commodity.

If a field should be readonly, you can declare a readonly property (this it with getter only).

The instance field variable initializers of a class correspond to a sequence of assignments that are executed immediately upon entry to any one of the instance constructors of that class. The variable initializers are executed in the textual order in which they appear in the class declaration.

A variable initializer for an instance field cannot reference the instance being created. Thus, it is a compile-time error to reference this in a variable initializer, as it is a compile-time error for a variable initializer to reference any instance member through a simple-name.

The default value initialization occurs for all fields, including fields that have variable initializers. Thus, when a class is initialized, all static fields in that class are first initialized to their default values, and then the static field initializers are executed in textual order. Likewise, when an instance of a class is created, all instance fields in that instance are first initialized to their default values, and then the instance field initializers are executed in textual order.

serhio
Not true. The compiler generates code to execute the inline initializers at the beginning of your constructor. You can step through the inline initializers.
Brannon
I removed "no difference". And I didn't say that you can't step through these lines.
serhio
It's not true that the constructor method is recommended. While it is true that you can't handle exceptions using the inline method, there is no difference in debugging. There are different reasons to use one method over another, but in the average case, they are equivalent and any "recommendations" are purely subjective.
Brannon
If you can't handle exceptions, why the constructor variansh should not be "recommended". I wonder when the inline method is more "recommended" that the constructor one.
serhio
+3  A: 

In fact the fields in both those classes could be readonly.

David M
+6  A: 

Apart from the number of lines of code, there are subtle differences.

Field initializations happen before constructors are run, for example. Doesn't make much of a difference in your example, but is something to keep in mind.

I would keep field initialsizations as in your second example to simple ones (strings or integers), to avoid possible exceptions occuring during initialization.

And as mentioned, in both ways the field can be readonly, as readonly fields can only be written to during construction.

Oded
A: 

The first one is useful if your "some arg" argument isn't static. If that arguments is only available through the constructor then this is the way to take. The second way comes with a problem. If an Exception gets thrown during instanciation of SomeClass there's no way of catching that Exception inside Class1.

Best wishes,
Fabian

halfdan
+8  A: 

There is a subtle difference, in that the field in the second example will be initialised before fields in the base class are initialised, and the field in the first example will be initialised after. This very rarely has any impact, however.

Largely it's a matter of style and preference. Personally I prefer the second, as it leaves the constructor clear for more logic based initialisation, but there is a strong case to make for having all initialisation done in the constructor.

Just for completeness, the order of initialisation goes:

  1. Static fields
  2. Static constructor
  3. Instance fields
  4. Base static fields
  5. Base static constructor
  6. Base instance fields
  7. Base constructor
  8. Constructor
ICR
So you actually prefer the second way, not the first :). +1 for the subtle difference though.
tzup
what about 7->8 when the base constructor is not explicitly called?
serhio
@serhio: the base constructor is always called, even if you do not make it explicit. If no explicit call to the base constructor is made, the default (parameterless) constructor is called at the start of the derived constructor (hence the reason for the compiler error if the base class does not provide a public or protected default constructor and you do not tell it which one to call).
Rory
A: 

There is very little difference. The compiler will place all of your inline initializers at the beginning of your constructor(s), in the order they were defined.

You might want to use the constructor approach if you need complex logic to initialize a field, otherwise I think the inline approach is more clear, and easier to maintain because the compiler handles calling it for you.

Brannon
A: 

Actually I prefer second one for readability and easy of debugging, you can wrap the call by try catch, but in the first you can not.

Ahmed Said
+1  A: 

There are differences.

Imagine you have a class with multiple constructors. Using the first way, each constructor would be required to create these objects. This may be intended behaviour, as you may want the object to be created differently each time. This extra responsibility on the contructor may be a bad thing, because if you don't remember to initialise the variable in each constructor you are going to end up with a null object.

There is a tiny amount of efficiency to consider but it is hardly significant - the first way requires two assignments, firstly to null and then the created object, while in the second way the object created and initialised all in one step.

Then think about static variables. Static variables MUST be declared the second way, because there is never any guarantee that instances of your class will be created.

DanDan
Usually you chain constructors together such that you have the initialisation logic in the most general constructor, then each constructor does it's specific bit then calls the more general constructor. That way you avoid the need for code duplication.
ICR
True, but at least you have the option of initialising the object as a different subclass or with different parameters.
DanDan
Also, static fields will only be initialised when the object is created whichever way you declare them, surely?
ICR
It does not make sense from a logical point of view to reinitialise the static members each time a new instance of your class is created.
DanDan
+4  A: 

You cannot make use of the this keyword when initializing fields inline. The reason for this is the order in which the code is executed: for all intents and purposes, the code to initialize a field inline is run before the constructor for the class (i.e. the C# compiler will prevent access to the this keyword). Basically what that means is this will not compile:

public class Class1
{
   private SomeClass someclass = new SomeClass(this);

   public Class1()
   {
   }
}

but this will:

public class Class1
{
   private SomeClass someclass;

   public Class1()
   {
       someclass = new SomeClass(this);
   }
}

It's a subtle difference, but one worth making a note of.

The other differences between the two versions are only really noticeable when using inheritance. If you have two classes which inherit from each other, the fields in the derived class will be initialized first, then the fields in the base class will be initialized, then the constructor for the base class will be invoked, and finally, the constructor for the derived class will be invoked. There are some cases where you need to be very careful with this, as it could cause a fruit salad of complications if you don't realise what is going on (one of which involves calling a virtual method inside the base class constructor, but that is almost never a wise move). Heres an example:

class BaseClass
{
 private readonly object objectA = new object(); // Second
 private readonly object objectB;

 public BaseClass()
 {
  this.objectB = new object(); // Third
 }
}

class DerivedClass : BaseClass
{
 private object objectC = new object(); // First
 private object objectD;

 public DerivedClass()
 {
  this.objectD = new object(); // Forth
 }
}

You will need to set breakpoints on all of the lines that initialize fields to be able to see the correct sequence.

Rory