Is there any difference between the two?

Is there a difference?

class example
{
    int i = 5;
}

class example2
{
    int i;

    public example2()
    {
        i = 5;
    }
}

      

I prefer the second one because I don't like giving values ​​after a variable declaration. But is there a technical difference?

+3


source to share


3 answers


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

}

      

+4


source


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.

+4


source


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.

+2


source







All Articles