3

違いはありますか?

class example
{
    int i = 5;
}

class example2
{
    int i;

    public example2()
    {
        i = 5;
    }
}

変数を宣言した後に値を与えるのは好きではないので、私は 2 番目の方法を好みます。しかし、技術的に違いはありますか?

4

3 に答える 3

4

はい。誰かがあなたのクラスから派生しexample2、基本クラスのコンストラクターを呼び出すのを忘れた場合、初期化がスキップされてしまう可能性があります。

コンストラクターのパラメーターに依存しない場合、(最初の例のように) 宣言の時点での初期化を好む傾向があります。

于 2013-02-14T02:20:30.303 に答える
4

簡単な答え :いいえ

長い答え:

生成された を見ると、クラスの初期化が行わIL codeれる場合example、コンストラクターを呼び出す前に、クラスのようにexample2クラスの初期化がコンストラクター内で行われます。

exampleクラス

.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

}

そしてexample2クラスのために

.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

}
于 2013-02-14T02:20:50.507 に答える
2

違いがある状況が発生する可能性があると言わざるを得ません(ただし、コードが質問に投稿されたものと同じくらい単純であれば、もちろん違いはありません)。

次のコードを検討してください。

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);
    }
}

そしてそれをテストする

new Class2().Foo();

出力は次のようになります。

i:5
j:0
i:5
j:5

手がかりは、初期化子 (フィールド宣言で値を割り当てるとき) が基本クラスのコンストラクターの前に実行されることです。そのため、コンストラクターFooから呼び出されたときは、デフォルト値、つまり. しかし、完全に作成された変数を呼び出したとき (コンストラクターが完了したとき) には、既に value があります。Class1j0Foonew Class2().Foo();Class2j5

基本クラスのコンストラクターでメソッドを呼び出すのは危険な設計ですが、virtual禁止されているわけではなく、注意が必要です。

以下は、C# による J.Richter CLR からの抜粋です。

コンパイラは、基本クラスのコンストラクターを呼び出す前に、便利な構文を使用してフィールドを初期化し、これらのフィールドが常にソース コードの外観が指示する値を持っているという印象を維持します。潜在的な問題は、基本クラスのコンストラクターが、派生クラスによって定義されたメソッドにコールバックする仮想メソッドを呼び出すときに発生します。これが発生した場合、便利な構文を使用して初期化されたフィールドは、仮想メソッドが呼び出される前に初期化されています。

于 2013-02-14T02:28:54.263 に答える