2009-07-21 5 views
8

オブジェクトの初期化時にオブジェクトを追加または削除する前に作成する必要があるリストなど、初期化が必要なフィールドを持つクラスがあります。フィールド定義またはクラスコンストラクタでのクラスフィールドの初期化

public class MyClass1 
{ 
    private List<MyOtherClass> _otherClassList; 

    public MyClass1() 
    { 
     this._otherClasslist = new List<MyOtherClass>(); 
    } 
} 


public class MyClass2 
{ 
    private List<MyOtherClass> = new List<MyOtherClass>(); 

    public MyClass2() 
    { 
    } 
} 

何この2つのクラス間の違いがあり、そしてなぜあなたは他の上で1つの方法を選ぶでしょうか?

私は通常、オブジェクトがインスタンス化されているときに起こるすべてのものを見るために1か所を見ることが容易であるため、MyClass1のようにコンストラクタのフィールドを設定しますが、 MyClass2のように直接フィールドを初期化する方が良いですか?

+0

をスニペットこのコードのバイナリに反射してこれを確認することができます。 –

答えて

5

C#コンパイラ(VS2008 sp1)によって生成されたILは、両方の場合(DebugビルドとReleaseビルドでも)ほぼ同等です。

あなた引数としてList<MyOtherClass>を取るパラメータ化コンストラクタを追加する必要がある場合は、そのようなコンストラクタでオブジェクトの非常に大きな数を作成するときしかし、それは、特に(異なるものになります)。

違いを見るには、&をVSにコピーして、ReflectorまたはILDASMのILを表示するようにビルドしてください。

using System; 
using System.Collections.Generic; 

namespace Ctors 
{ 
    //Tested with VS2008 SP1 
    class A 
    { 
     //This will be executed before entering any constructor bodies... 
     private List<string> myList = new List<string>(); 

     public A() { } 

     //This will create an unused temp List<string> object 
     //in both Debug and Release build 
     public A(List<string> list) 
     { 
      myList = list; 
     } 
    } 

    class B 
    { 
     private List<string> myList; 

     //ILs emitted by C# compiler are identicial to 
     //those of public A() in both Debug and Release build 
     public B() 
     { 
      myList = new List<string>(); 
     } 

     //No garbage here 
     public B(List<string> list) 
     { 
      myList = list; 
     } 
    } 

    class C 
    { 

     private List<string> myList = null; 
     //In Release build, this is identical to B(), 
     //In Debug build, ILs to initialize myList to null is inserted. 
     //So more ILs than B() in Debug build. 
     public C() 
     { 
      myList = new List<string>(); 
     } 

     //This is identical to B(List<string> list) 
     //in both Debug and Release build. 
     public C(List<string> list) 
     { 
      myList = list; 
     } 
    } 

    class D 
    { 
     //This will be executed before entering a try/catch block 
     //in the default constructor 
     private E myE = new E(); 
     public D() 
     { 
      try 
      { } 
      catch (NotImplementedException e) 
      { 
       //Cannot catch NotImplementedException thrown by E(). 
       Console.WriteLine("Can I catch here???"); 
      } 
     } 
    } 

    public class E 
    { 
     public E() 
     { 
      throw new NotImplementedException(); 
     } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      //This will result in an unhandled exception. 
      //You may want to use try/catch block when constructing D objects. 
      D myD = new D(); 
     } 
    } 
} 

注:ビルドをリリースするために切り替えたときに、私は任意の最適化フラグを変更しませんでした。

0

コードは等価です。なぜなら、2番目のケースではすべてのコンストラクタに初期化子を置く必要があります.2番目のケースの利点は、そのクラスを作成してから1年後に新しいコンストラクタを追加するときにプログラマがフィールドを初期化するとは思わないことです。

+0

クラスを最初に作成した開発者は、適切なコンストラクタチェインを使用する必要があります。しかし、1年後にクラスを修正するプログラマは、クラスに触れる前にクラスをよく理解しています。彼はすべてのフィールドが正しく初期化されていることを確認する必要があります。 –

0

c#では、2つの例の間に実質的な違いはありません。しかし、開発者はエラーが発生しにくいため、コンストラクタでフィールドを初期化する傾向があります。

2

コンストラクタで初期化するときに、必要であれば例外をキャッチして処理する方が簡単だと思います。

1

MyClass1では、誰かがコンストラクタをオーバーライドして問題を引き起こす可能性があります。

3

は1つの違いあり:

フィールドが呼び出されるオブジェクト インスタンスのコンストラクターの直前に 初期化されるので、 コンストラクタは フィールドの値を割り当てた場合、それは任意の値を上書きします フィールド宣言中に与えられる。 From MSDN

3

動作は両方とも同じでなければなりません。
しかし、あなたが考慮したいと思うかもしれないものは、縁のケースIL - Bloatです。フィールドイニシャライザのILは、各ctorの先頭に挿入されます。それで、多くのフィールドイニシャライザ多くのオーバーロードされたctorsがある場合、ILの同じセクションがctor過負荷ILに接頭されます。その結果、コンストラクターチェーンを使用するか、共通のInitialize()関数(反復ILがメソッド呼び出しになる)に委譲する場合に比べて、アセンブリの合計サイズが大きくなる可能性があります。したがって、この特定のシナリオでは、フィールド初期化子は比較的弱い選択肢になります。

は、あなたは彼らがすでにデフォルト値...それらを再度INITする必要はありませんがあり

public class MyClass2 
    { 
    private List<int> whack = new List<int>(); 
    // lots of other field initializers 

    public MyClass2() 
    { 
     Console.WriteLine("Default ctor"); 
    } 
    public MyClass2(string s) 
    { 
     Console.WriteLine("String overload"); 
    } 
     // lots of other overload ctors 
    } 
関連する問題