Каков тип параметра для универсального параметра функции при вызове из базового класса с помощью this. - PullRequest
4 голосов
/ 15 июля 2011

Запутанный вопрос, я знаю.Учитывая следующее:

    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 в первом случае?

Заранее спасибо!

Ответы [ 2 ]

14 голосов
/ 15 июля 2011

Если не задействован «динамический» тип, разрешение перегрузки и определение типа выполняются во время компиляции , а не во время выполнения .

Когда разрешение перегрузки видит Test.GenericFunc(this);, оно должно вывести аргумент универсального типа, соответствующий отсутствующему параметру универсального типа. Это простая проблема; он использует время компиляции типа this, а внутри метода BaseType, явно время компиляции типа this всегда BaseType.

Следовательно, разрешение перегрузки предполагает, что вы намеревались вызвать Test.GenericFunc<BaseType>(this).

Если вы хотите, чтобы это работало во время выполнения, вы можете сделать это в C # 4. Просто скажите Test.GenericFunc((dynamic)this). Это снова запустит механизм разрешения перегрузки во время выполнения, после чего будет притворяться, что вы произвели приведение this к его типу выполнения обратно во время компиляции.

Да, это так же дорого, как кажется. Если вам нужен семантический анализ во время выполнения, нам нужно запустить семантический анализатор во время выполнения.

6 голосов
/ 15 июля 2011

Потому что это:

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().

Во втором случае компилятор выводит тип как DerivedType непосредственно из использования и, следовательно, GenericFunc получает T = DerivedType.

...