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

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

    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 ответа

Решение

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

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,

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

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

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

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

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

Другие вопросы по тегам