2009-03-23 18 views
2

私は誰が このコードのスニペットの1行の構文を説明できるかどうか疑問:依存性注入とC#構文

public class ContactController : Controller 
{ 
    private IContactManagerRepository _repository; 

    **public ContactController() 
     : this(new EntityContactManagerRepository())** 
    {} 


    public ContactController(IContactManagerRepository repository) 
    { 
     _repository = repository; 
    } 

ビットを、私は最初のコンストラクタであるで特に興味を持っています。それは確かに を参照しないこと(新しいEntityContactManagerRepository()) 最初のコンストラクタが第二を呼び出し、私はこの上 を置くとインテリセンスが私に語ったこと - (リスト3 http://www.asp.net/learn/mvc/tutorial-29-cs.aspx)私は からそれを得た記事から理解 2番目のコンストラクタです。しかし、前に の後にコロンでコンストラクタを見たことはありません。私はクラス宣言のコロンは、ContactControllerがControllerから継承した コンパイラに伝えますが、コンストラクタ内のコロンは何をしますか?

答えて

5

あなたが言ったように、それは実行の最初の部分としてもう一方のコンストラクタを呼び出します。別の方法として、代わりに基本クラスのコンストラクタを呼び出すbaseを使用する方法があります。言語仕様では、この呼び出しにはというコンストラクタ初期化子という用語が使用されています。 常にのようなものです。何も指定しなければ、それはbase()の呼び出しに相当します。言い換えれば:

public Foo(int x) 

Fooコンストラクタの本体が実行される前に、基本クラスのパラメータなしのコンストラクタが呼び出され、両方のケースで

public Foo(int x) : base() 

に相当します。コンパイラは、無限ループにならないようにします。すべての(静的でない)クラスには、基本クラスのコンストラクタを呼び出すコンストラクタが少なくとも1つ必要です。 "this"クラスのコンストラクタ本体が実行される前に、常に基本クラスのコンストラクタを呼び出すことになります。

しかし、Javaとは異なり、インスタンス変数の初期化子は、基本クラスのコンストラクタが呼び出す前に実行されます。です。

詳細については、article about constructor chainingをご覧ください。

3

constructor chainingと呼ばれます。この構文では、基本クラスのコンストラクタまたは現在のクラスの別のコンストラクタを呼び出すことができます。

0

コロンは、あなたが(あなたの例のように)同じクラスの別のコンストラクタを呼び出しているか、この構文:base(..args...)

を使用して、基本クラスからのコンストラクターは、あなたがしていることを強制するために使用されていることを示すために使用されます余分な作業を行う前に他のコンストラクタやベースコンストラクタを呼び出すことができます(つまり、ベースクラスの最初の初期化順序が保証されます)。

1

この例では、コンストラクタチェーンを使用しています。私。デフォルトのコンストラクタは、同じ型の引数を持つ特定のコンストラクタを呼び出します。これを行うには、thisキーワードを、例のように必要な引数とともに使用します。

同様の機能は、baseキーワードの使用です。クラス階層があるときは、常に階層内のすべての型のコンストラクタを呼び出します。たとえば、BクラスとDクラスを持っている場合、Dのインスタンスを作成すると、Bのコンストラクタが呼び出され、次にDのコンストラクタが呼び出されます。デフォルトコンストラクタ(引数なし)では、何もする必要はありません。しかし、Bが引数を必要とするコンストラクタしか実装していない場合は、これをDのコンストラクタから渡す方法が必要です。これを行うには、例でthisが使用されているのと同様のキーワードbaseを使用します。

1

これは、省略可能な/省略時のパラメータのサポートがない結果(回避策)です。あなたが好きな状況で自分自身を見つけることができます。これらの場合

MessageBox.Show(string) 
... 
MessageBox.Show(Window, string, string) 
... 
MessageBox.Show(Window, string, string, MessageBoxButton, MessageBoxImage, MessageBoxResult, MessageBoxOptions) 

、通常、ほとんどのパラメータを持つ1は、実装が含まれており、他のオーバーロードは、単にデフォルトのパラメータで1つを呼び出します。注意すべき点の1つは、パラメータの数がNに増加すると、オーバーロードの数がN!に増加する可能性があるということです。

コンストラクタは特殊機能です。そのため、それらの値を扱う必要があります。オブジェクトは一度しか構築できません。通常の関数では、実装関数を何度でも呼び出すことができます。ここでは、の実装者のコンストラクタを呼び出す必要があります。の最初の処理はです。コンストラクタ連鎖構文は、これらの要件を指摘しています。

元の問題に戻ります。これらのケースは非常に一般的ではないにもかかわらず、あなたはパラメータとして使用されます(ここではC#3.0の機能を使用して)新しい型を定義することによって、この問題を克服することができます

ここ
public class Parameter 
{ 
    public string P1 { get; set; } 
    public int P2 { get; set; } 
    public string P3 { get; set; } 
    public double P4 { get; set; } 
    ... 
    public Parameter() 
    { 
     P1 = "p1"; 
     P2 = 2; 
     P3 = "p3"; 
     P4 = 4.0; 
     ... 
    } 
} 
... 
FunctionWithManyParametersCanNowBeCalledLike(new Parameter() { P2 = -2 }); 

我々はコンストラクタでデフォルトパラメータを提供します。これは多くのコンストラクタの解決策ですか? No.

C#4.0には、オプションの名前付きパラメータ機能が含まれています。したがって、新しいパラメータ型を定義する必要はありません。あなたは、そのための構文的な砂糖として機能を考えるかもしれませんが、それらは異なります。我々はまだの基本クラスのコンストラクタのこの構文を必要とします。