Is there any difference between the two?
Short answer: No
Long answer:
If you look at the generated IL code
, in case example
the initialization of the class is performed, before the call to the constructor, where in the example2
initialization of the class of the class is done inside the constructor.
example
class
.class private auto ansi beforefieldinit example
extends [mscorlib]System.Object
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed
{
.maxstack 8
L_0000: ldarg.0
L_0001: ldc.i4.5
L_0002: stfld int32 ConsoleApplication1.example::i
L_0007: ldarg.0
L_0008: call instance void [mscorlib]System.Object::.ctor()
L_000d: ret
}
.field private int32 i
}
and for example2
Class
.class private auto ansi beforefieldinit example2
extends [mscorlib]System.Object
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed
{
.maxstack 8
L_0000: ldarg.0
L_0001: call instance void [mscorlib]System.Object::.ctor()
L_0006: ldarg.0
L_0007: ldc.i4.5
L_0008: stfld int32 ConsoleApplication1.example2::i
L_000d: ret
}
.field private int32 i
}
source to share
Yes. If someone comes from your class example2
and forgets to call the constructor of the base class, then initialization is skipped, which can be bad.
I prefer initialization at the point of declaration (as in the first example) if there is no dependency on constructor parameters.
source to share
I have to say that there may be situations where there is a difference (although if the code is as simple as the one posted in the question, of course there is no difference).
Consider the following code:
public class Class1
{
public Class1()
{
Foo();
}
public virtual void Foo()
{
}
}
public class Class2 : Class1
{
protected int i = 5;
protected int j;
public Class2()
{
j = 5;
}
public override void Foo()
{
Console.WriteLine("i:" + i);
Console.WriteLine("j:" + j);
}
}
and test it
new Class2().Foo();
The output will be as follows:
i:5
j:0
i:5
j:5
The key is that the initializer (when you assign the value to the right in the field declaration) runs before the base class constructor. So, when Foo
called from the constructor Class1
j
has a default value, that is 0
. But when we call Foo
on a fully created variable new Class2().Foo();
(when the constructor is Class2
complete) it j
already matters 5
.
Although this is a dangerous design, virtual
it is not forbidden to call methods in the constructor of the base class, and you should be aware of this.
Here is an excerpt from J.Richter CLR via C #:
The compiler initializes any fields using convenient syntax before calling the base class constructor to maintain the impression that these fields always matter as the look of the source code dictates. A potential problem occurs when the base class constructor calls a virtual method that returns a method defined by a derived class. If this happens, the fields that were initialized using convenience syntax were initialized before the virtual method was called.
source to share