4

紛らわしい質問ですね。以下を考えると:

    class Test
    {
        public static void GenericFunc<T>(T SomeType)
        {
            System.Console.WriteLine("typeof(T): " + typeof(T).Name);
            System.Console.WriteLine("SomeType.GetType(): " + SomeType.GetType().Name);
        }
    }

    public class BaseType
    {
        public void RunTest() { Test.GenericFunc(this); }
    }

    public class DerivedType : BaseType { }

次のコードは、興味深い出力を生成します。

    DerivedType Derived = new DerivedType();
    Derived.RunTest();

    // output:
    // typeof(T): BaseType
    // SomeType.GetType(): DerivedType

ただし、これは期待どおりに動作します。

    Test.GenericFunc(new Derived());

    // output:
    // typeof(T): DerivedType
    // SomeType.GetType(): DerivedType

最初のケースで T が BaseType として評価されるメカニズムを理解するのを手伝ってくれる人はいますか?

前もって感謝します!

4

2 に答える 2

14

「動的」型が含まれていない限り、オーバーロードの解決と型の推論は、実行時ではなくコンパイル時に実行されます。

オーバーロードの解決Test.GenericFunc(this);で、欠落しているジェネリック型パラメーターに対応するジェネリック型引数を推測する必要があることがわかります。これは簡単な問題です。のコンパイル時の型を使用し、thisのメソッド内ではBaseType、明らかにコンパイル時の型thisは常にBaseTypeです。

したがって、オーバーロードの解決では、 を呼び出すつもりであると想定されますTest.GenericFunc<BaseType>(this)

これをランタイムで処理する場合は、C# 4 で実行できますTest.GenericFunc((dynamic)this)これにより、実行時にオーバーロード解決エンジンが再び開始さthisれ、コンパイル時に実行時の型にキャストされたふりをします。

はい、それは聞こえるほど高価です。実行時にセマンティック分析が必要な場合は、実行時にセマンティック アナライザーを実行する必要があります。

于 2011-07-14T20:57:32.903 に答える
6

これのため:

public class BaseType
{
    public void RunTest() { Test.GenericFunc(this); }
}

基本的には以下と同等です:

public class BaseType
{
    public void RunTest() { Test.GenericFunc<BaseType>(this); }
}

したがって、GenericFuncはコンパイル時に でインスタンス化されますT = BaseType。ただし、this実行時に渡すオブジェクトは、取得する派生型ですSomeType.GetType()

2 番目のケースでは、コンパイラはDerivedType使用法から直接型を推測するためGenericFunc、 でインスタンス化されT = DerivedTypeます。

于 2011-07-14T20:51:43.967 に答える