Почему Type.IsGenericType возвращает TRUE для Task без возвращаемого типа, полученного путем отражения от метода, но typeof (Task) .IsGenericTyp возвращает FALSE - PullRequest
0 голосов
/ 21 сентября 2018

Может кто-нибудь объяснить это?Согласно документации IsGenericType

указывает, представляет ли текущий тип параметр типа в определении универсального типа или метода.

Итак, это (LINQPad) код:

bool bStraight = typeof(Task).IsGenericType;
bStraight.Dump("typeof(Task).IsGenericType");

работает как положено и выдает результат:

typeof (Task) .IsGenericType
False

Но когдаЯ извлекаю его из метода с помощью отражения:

public class MyClass
{
    public async Task Method()
    {
        await Task.Run(() =>
        {
            Thread.Sleep(3000);
        });
    }
}

public async Task TEST()
{
    MyClass theObject = new MyClass();

    Task task = (Task)typeof(MyClass).GetTypeInfo()
                            .GetDeclaredMethod("Method")
                            .Invoke(theObject, null);

    bool b = task.GetType().IsGenericType;  
    bool b2 = task.GetType().GetGenericTypeDefinition() == typeof(Task<>);
    b.Dump("IsGenericType");
    b2.Dump("GetGenericTypeDefinition");

    bool bStraight = typeof(Task).IsGenericType;
    bStraight.Dump("typeof(Task).IsGenericType");
}

Я получаю неожиданный вывод:

IsGenericType
True

GetGenericTypeDefinition
True

1 Ответ

0 голосов
/ 21 сентября 2018

В некоторых ситуациях фреймворк возвращает Task<VoidTaskResult>, замаскированный под Task.Представьте, что у вас есть логика, опирающаяся на TaskCompletionSource<T>.Если вы на самом деле не собираетесь возвращать результат, вам все равно нужно заполнить универсальный параметр T.Вы можете использовать TaskCompletionSource<object>, но вы потеряете память на указатель (4 байта в 32 битах, 8 байтов в 64 битах).Чтобы избежать этого, фреймворк использует пустую структуру: VoidTaskResult.

...