37

たとえば、次のようなタイプがあります。

public class EffectOptions
{
    public EffectOptions ( params object [ ] options ) {}

    public EffectOptions ( IEnumerable<object> options ) {}

    public EffectOptions ( string name ) {}

    public EffectOptions ( object owner ) {}

    public EffectOptions ( int count ) {}

    public EffectOptions ( Point point ) {}

}

ここでは、コンストラクターを使用した例を示しただけですが、型自体の非コンストラクター メソッドの場合、結果は同じになりますよね?

だからあなたがするとき:

EffectOptions options = new EffectOptions (null);

どのコンストラクターが呼び出され、その理由は?

私はこれを自分でテストすることができましたが、過負荷解決システムがどのように機能するかを理解したいと思っています (それが呼ばれているかどうかはわかりません)。

4

2 に答える 2

83

正確なルールについては、オーバーロード解決の仕様を参照してください。ざっくりですが、こんな感じです。

まず、アクセス可能なすべてのコンストラクターのリストを作成します。

public EffectOptions ( params object [ ] options )
public EffectOptions ( IEnumerable<object> options ) 
public EffectOptions ( string name )
public EffectOptions ( object owner ) 
public EffectOptions ( int count ) 
public EffectOptions ( Point point )

次に、適用できないコンストラクターをすべて削除します。適用可能なコンストラクターとは、すべての仮パラメーターに対応する引数があり、その引数が暗黙的に仮パラメーターの型に変換できるコンストラクターです。Point が値型であると仮定して、"int" および "Point" バージョンを除外します。それは去る

public EffectOptions ( params object[] options )
public EffectOptions ( IEnumerable<object> options ) 
public EffectOptions ( string name )
public EffectOptions ( object owner ) 

ここで、「params」を含むものが展開された形式または展開されていない形式で適用できるかどうかを検討する必要があります。この場合、両方の形式に適用できます。その場合は、展開されたフォームを破棄します。だからそれは去る

public EffectOptions ( object[] options )
public EffectOptions ( IEnumerable<object> options ) 
public EffectOptions ( string name )
public EffectOptions ( object owner ) 

次に、適用可能な候補の中から最適なものを決定する必要があります。最良のルールは複雑ですが、短いバージョンでは、より具体的であるほど具体的でないよりも優れています。キリンは哺乳類よりも具体的であり、哺乳類は動物よりも具体的であり、動物は物体よりも具体的です。

バージョンはそれらobjectすべてよりも具体的ではないため、削除できます。バージョンはIEnumerable<object>バージョンより具体的ではないobject[]ため (理由がわかりますか?)、削除することもできます。それは去る

public EffectOptions ( object[] options )
public EffectOptions ( string name )

そして今、私たちは立ち往生しています。object[]は よりも具体的ではありませんstring。したがって、これによりあいまいなエラーが発生します。

これは簡単なスケッチです。実際のタイブレーク アルゴリズムははるかに複雑です。しかし、それらは基本です。

于 2011-03-02T23:20:58.207 に答える
9

この場合、C# コンパイラはコンストラクターを選択せず​​、代わりにエラーになります。この値nullは、使用可能なコンストラクターのいくつかで有効であり、1 つを選択するにはタイ ブレーク ロジックが不十分であるため、エラーが発生します。

C# コンパイラのオーバーロード解決ロジックは複雑なプロセスですが、そのしくみの簡単な (本質的に不完全な) 概要は次のとおりです。

  • 指定された名前を持つすべてのメンバーを収集します
  • 指定された引数と互換性があり、適切なアクセシビリティを備えたパラメーター リストを持つメンバーにメンバーをフィルター処理します。
  • 残りのメンバーに複数の要素がある場合は、タイ ブレーク ロジックを使用して最適な要素を選択します。

詳細は、C# 言語仕様のセクション 7.4 に記載されています。そして、エリックがすぐに来て、より正確な説明をしてくれると確信しています:)

于 2011-03-02T20:59:00.390 に答える