2012-04-02 42 views
7

私は、次の簡単なコードオーバーロードされたオーバーライドされたメソッドを呼び出す方法

abstract class A 
{ 
    public abstract void Test(Int32 value); 
} 

class B : A 
{ 
    public override void Test(Int32 value) 
    { 
     Console.WriteLine("Int32"); 
    } 

    public void Test(Double value) 
    { 
     Test((Int32)1); 
    } 
} 

私はこのコードを実行したときのラインテスト((のInt32が)1)による無限再帰にスタックオーバーフローが発生しています。正しく私が見つけた(整数パラメータ付き)適切なメソッドを呼び出すための唯一の可能な方法は

(this as A).Test(1); 

である。しかし、両方の方法がテスト公開され、私は、ユーザーが両方を呼び出すことができて喜んでいるので、これは、私のために適切ではありません方法?

答えて

4

残念ながらA::Test(int)からBへの参照を呼び出すには、何らかのキャストが必要です。 C#コンパイラがBの参照を参照する限り、それはB::Test(double)バージョンを選択します。

Aわずかに少ない醜いバージョンは、しかし、次の

​​

もう一つ考えられるの両方がフィードに別の名前でプライベートメソッドを持っています。ご想像のとおりC#で

class B : A { 
    public override void Test(int i) { 
    TestCore(i); 
    } 
    public void Test(double d) { 
    TestCore(1); 
    } 
    private void TestCore(int i) { 
    // Combined logic here 
    } 
} 
5

メソッドのオーバーロードの解決は、常に動作しませんが、あなたのコードが仕様に従って動作している(私はしばらく前にこのことについてa blog postを書きました)。

要するに

、コンパイラは、またはそのベースの1(あなたのケースBに)

  • がタイプで宣言されている(あなたのケースTestに)

    • は、同じ名前を持つメソッドを見つけることから始め種類
    • をオーバーライド修飾子最後のポイント

    注意して宣言されていません。仮想メソッドはコンパイル時ではなく実行時に解決されるため、実際は論理的です。

    最後に、タイプ(この場合はB)が候補であるメソッド(呼び出しのパラメータを候補メソッドのパラメータタイプに暗黙的に変換できることを意味する)がある場合、そのメソッドが使用されます。オーバーライドされたメソッドは、決定プロセスの一部ではありません。

    オーバーライドされたメソッドを呼び出す場合は、最初にオブジェクトをその基本型にキャストする必要があります。

  • 関連する問題