web-dev-qa-db-ja.com

C#の継承とデフォルトのコンストラクター

基本クラスAと、Bから派生したクラスAがあるとします。次に、クラスAのコンストラクターがクラスBに継承されることはありません。ただし、Bの新しいオブジェクトが作成されると、クラスAのデフォルト/カスタムコンストラクターが呼び出される前に、クラスBのデフォルトコンストラクターが呼び出されます。たぶんこれの目的は、クラスAのフィールドをデフォルト値に初期化する必要があることです。

ここで、クラスAがカスタムコンストラクターを定義したとします。これは、クラスAのデフォルトコンストラクターがコンパイラによって暗黙的に削除されることを意味します。さて、クラスBの新しいインスタンスを作成すると、クラスAのコンストラクターを呼び出す前に、クラスBのどのコンストラクターが自動的に呼び出されますか? (このような場合、クラスAフィールドはどのように初期化されますか?)

41
helloworld

さて、クラスBの新しいインスタンスを作成すると、クラスAコンストラクターを呼び出す前に、クラスBのどのコンストラクターが自動的に呼び出されますか?

基本的に、コードはコンパイルに失敗します。各コンストラクターは、暗黙的または明示的に別のコンストラクターにチェーンする必要があります。チェーンするコンストラクターは、同じクラス(thisを使用)または基本クラス(baseを使用)に含めることができます。

このようなコンストラクタ:

_public B() {}
_

暗黙的に:

_public B() : base() {}
_

...そして、コンストラクタをまったく指定しない場合、同じ方法で暗黙的に追加されますが、それでも何か呼び出す必要があります。たとえば、あなたのシナリオ:

_public class A
{
    public A(int x) {}
}

public class B : A {}
_

次のコンパイラエラーが発生します。

エラーCS7036:必要な仮パラメータ_'x'_ of 'A.A(int)'に対応する引数が指定されていません

ただし、別のコンストラクター呼び出しを明示的に指定できます。

_public B() : base(10) {} // Chain to base class constructor
_

または

_public B() : this(10) {} // Chain to same class constructor, assuming one exists
_
57
Jon Skeet

コンストラクターの実行が完了すると、オブジェクトは有効な初期状態にあります有効なオブジェクトを使用することになります。
クラスAにデフォルト以外のコンストラクターを提供する場合-事実上、クラスAオブジェクトを構築するには、つまり有効な初期状態にするには-パラメーターによって提供される、より多くの情報が必要です。
これを考えると、コンパイラーはnotによってデフォルトのコンストラクターを生成します。クライアントコードはコンパイルに失敗します(必要な場合-オブジェクトを有効な状態にする方法は他にありますか?)-クライアントプログラマーは座って注意する必要があります。
明示的な空のコンストラクターを提供する場合-コンパイラーに効果的に伝えている-私は何をしているのかを知っています-デフォルトのコンストラクターはおそらくフィールドを適切なデフォルト値に初期化するでしょう。
または再利用を促進するために-デフォルトのコンストラクターは、いくつかのデフォルト値を使用してデフォルト以外のコンストラクターを呼び出すことができます。
サブクラスはそのスーパークラスを知っています-サブクラスのコンストラクターはスーパークラスのメソッドを呼び出すことができます(サブクラスで一般的に再利用されるメソッド)。上記を考えると、スーパークラス部分は有効な状態-つまり、メソッド呼び出しの前にコンストラクターが実行されたである必要があります。これには、サブクラスコンストラクターの前にスーパーコンストラクターを呼び出す必要があります。
これを考えると、正しい初期状態の動作を実施するようにコンストラクターを簡単に設計できます。

3
atul