13

呼び出されるメソッドは実行時に決定されると思いましたか、それとも何か見逃していましたか? サンプルコード:

class Program
{
    static void Main(string[] args)
    {
        var magic = new MagicClass();
        magic.DoStuff(new ImplA());
        magic.DoStuff(new ImplB());
        Console.ReadLine();
    }
}
class MagicClass
{
    internal void DoStuff<T>(T input) where T : SomeBase
    {
        HiThere(input);
    }

    void HiThere(SomeBase input)
    {
        Console.WriteLine("Base impl");
    }

    void HiThere(ImplA input)
    {
        Console.WriteLine("ImplA");
    }

    void HiThere(ImplB input)
    {
        Console.WriteLine("ImplB");
    }
}

abstract class SomeBase
{

}
class ImplA : SomeBase{}
class ImplB : SomeBase{}

私は得ると思った:

ImplA
ImplB

出力としてですが、印刷されますBase impl。入力をキャストせずにオーバーロードされたメソッドを取得するためにできることはありますか?

4

2 に答える 2

18

オーバーロードはコンパイラによって選択されます。電話の場合はこちら:

internal void DoStuff<T>(T input) where T : SomeBase
{
    HiThere(input);
}

SomeBaseコンパイル時にそれがすべてであるため、 を持つものを選択します。

おそらく最も必要なのはオーバーライドです。これは、別のロジックを SomeBase の継承者に入れる必要があることを意味します。

abstract class SomeBase
{
  abstract string Name { get; }
}
class ImplA : SomeBase{ override string Name { get { return "ImplA"; } } }
class ImplB : SomeBase{ override string Name { get { return "ImplB"; } } }

void HiThere(SomeBase input)
{
    Console.WriteLine(input.Name);
}
于 2013-04-12T07:59:59.130 に答える
4

コンパイル中にオーバーロードが選択されます。
オーバーライドは実行時に選択されます。

ここで、コンパイラは T を に代入できることだけを知っていますがSomeBase、それ以外は何も知りません。実際、期待どおりに機能した場合は、そのwhere T : SomeBase部分を完全にスキップできます。必要な理由は、提供されたオブジェクトで何を呼び出すことができるかを確認するために、コンパイラがその情報を知る必要があるためです。

于 2013-04-12T08:03:33.417 に答える