Почему GetType возвращает System.Int32 вместо Nullable ? [дубликат]

На этот вопрос уже есть ответ здесь:

Почему выводится этот фрагмент System.Int32 вместо Nullable ?

int? x = 5;
Console.WriteLine(x.GetType());
29
задан Arghya C 4 November 2015 в 18:09
поделиться

3 ответа

GetType() является методом object.
Чтобы вызвать его, структура Nullable<T> должна быть в штучной упаковке.

Вы можете увидеть это в коде IL:

//int? x = 5;
IL_0000:  ldloca.s    00 
IL_0002:  ldc.i4.5    
IL_0003:  call        System.Nullable<System.Int32>..ctor

//Console.WriteLine(x.GetType());
IL_0008:  ldloc.0     
IL_0009:  box         System.Nullable<System.Int32>
IL_000E:  callvirt    System.Object.GetType
IL_0013:  call        System.Console.WriteLine

Обнуляемые типы обрабатываются специально CLR; невозможно иметь упакованный экземпляр обнуляемого типа.
Вместо этого, упаковывая обнуляемый тип, вы получите пустую ссылку (если HasValue false) или упакованное значение (если есть значение).

Следовательно, инструкция box System.Nullable<System.Int32> приводит к выводу в штучной упаковке Int32, а не в штучной упаковке Nullable<Int32>.

Поэтому GetType() невозможно когда-либо возвращать Nullable<T>.

Чтобы увидеть это более четко, посмотрите на следующий код:

static void Main()
{
    int? x = 5;
    PrintType(x);   
}
static void PrintType<T>(T val) {
    Console.WriteLine("Compile-time type: " + typeof(T));
    Console.WriteLine("Run-time type: " + val.GetType());
}

Это печатает

Тип времени компиляции: System.Nullable`1 [System.Int32]
Тип времени выполнения: System.Int32

29
ответ дан 28 November 2019 в 01:47
поделиться

GetType() не является виртуальным, и поэтому определяется только на object. Таким образом, чтобы сделать звонок, Nullable<Int32> должен быть сначала помещен в коробку. У Nullables есть особые правила бокса, поэтому в коробку помещается только значение Int32, и это тип сообщения.

8
ответ дан 28 November 2019 в 01:47
поделиться

Потому что тип «5» является int.

Если вы хотите определить, является ли тип обнуляемым, и базовый тип, используйте что-то вроде этого:

public static Type GetActualType(Type type, out bool isNullable)
{
    Type ult = Nullable.GetUnderlyingType(type);
    if (ult != null)
    {
        isNullable = true;
        return ult;
     }
     isNullable = false;
     return type;
}
1
ответ дан 28 November 2019 в 01:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: