11

基本クラスがありますA

public class A
{
    public virtual void Method(A parameter)
    {
        Console.WriteLine(MethodBase.GetCurrentMethod());
    }
    public virtual void Method(B parameter)
    {
        Console.WriteLine(MethodBase.GetCurrentMethod());
    }
}

内在B

public class B : A
{
    public virtual void Method(object parameter)
    {
        Console.WriteLine(MethodBase.GetCurrentMethod());
    }

    public override void Method(A parameter)
    {
        Console.WriteLine(MethodBase.GetCurrentMethod());
    }

    public override void Method(B parameter)
    {
        Console.WriteLine(MethodBase.GetCurrentMethod());
    }
}

S拡張メソッドを持つ静的クラス

public static class S
{
    public static void Method(this B instance, B parameter)
    {
        Console.WriteLine(MethodBase.GetCurrentMethod());
    }
}

タイプのインスタンスを作成してそれをB呼び出す例では、実際の結果はです。Methodpublic override void Method(B parameter)public virtual void Method(object parameter)

var b = new B();
b.Method(new B()); // B.Method (Object parameter) Why???

コンパイラがより適切な方法を選択しないのはなぜですか? UPDそしてなぜそれは拡張メソッドではないのですか?

4

1 に答える 1

10

コンパイラがより適切な方法を選択しないのはなぜですか?

言語仕様のルールに従っているため、派生クラスに該当するものがない場合を除き、基本クラスで最初に宣言された候補メソッド(派生クラスでオーバーライドされた場合)は、候補メソッドを見つけるときに無視されます。メソッド、その時点で検索は基本クラスなどに移動します。

これは「脆弱な基本クラス」の問題を回避するように設計されていますが、派生クラスでメソッドがオーバーライドされているため、飲み込むのは難しいと思います。

C#4仕様の関連ビットは7.4で、これは次のように終わります。

タイプパラメータとインターフェイス以外のタイプでのメンバールックアップ、および厳密に単一継承であるインターフェイスでのメンバールックアップ(継承チェーン内の各インターフェイスには正確にゼロまたは1つの直接ベースインターフェイスがあります)の場合、ルックアップルールの効果は単純に派生したものです。メンバーは、同じ名前または署名を持つベースメンバーを非表示にします。

編集:拡張メソッドについて...

そして、なぜそれが拡張メソッドではないのですか?

仕様のセクション7.6.5.2から:

フォームの1つのメソッド呼び出し(§7.5.5.1)

expr . identifier ( )
expr . identifier ( args )
expr . identifier < typeargs > ( )
expr . identifier < typeargs > ( args )

呼び出しの通常の処理で適用可能なメソッドが見つからない場合は、拡張メソッド呼び出しとして構成を処理しようとします。

したがって、拡張メソッドは、基本的に最後の手段としてのみ使用されます。

于 2012-08-24T13:41:38.060 に答える