Каково использование Nullable.GetUnderlyingType, если typeof (int?) Является Int32?

почему typeof int? a Int32

int? x = 1;
Console.WriteLine(x.GetType().Name);

Если все в порядке, то какое использование Nullable.GetUnderlyingType?

Ответ 1

Вызов GetType() блокирует вашу переменную. CLR имеет специальное правило, что Nullable<T> помещается в поле T. Поэтому x.GetType вернет Int32 вместо Nullable<Int32>.

int? x = 1;
x.GetType() //Int32
typeof(int?) //Nullable<Int32>

Так как a Nullable, содержащий null, помещается в квадрат null, следующее исключает:

int? x = null;
x.GetType() //throws NullReferenceException

Процитировать MSDN по боксу Nullable Types:

Объекты, основанные на типах с нулевым значением, помещаются только в поле, если объект не равен нулю. Если HasValue - false, ссылка на объект присваивается null вместо бокса

Если объект не является нулевым - если HasValue - true - тогда происходит бокс, но вставляется только базовый тип, на который основан объект с нулевым значением. Бокс не равный null null value type вводит тип значения сам, а не System.Nullable<T>, который обертывает тип значения.

Ответ 2

Этот пример немного запутан, потому что:

int? x = 1;

создает Nullable<int>, как вы ожидаете; Однако:

Type tupe = x.GetType();

- это вызов не виртуального метода на object, который не является (и не может быть) переопределен - поэтому это операция бокса; и Nullable<T> имеет специальные правила бокса:

  • Если он пуст, он помещается в null
  • если он имеет значение, значение помещается в поле и возвращается

то есть.

int? x = 1;
int y = 1;

в поле точно.

Следовательно, вы проходите typeof(int) до GetUnderlyingType.

Более наглядным примером того, когда это помогает, является использование рефлексии:

class Foo {
    public int? Bar {get;set;}
}
...
Type type = typeof(Foo); // usually indirectly
foreach(var prop in type.GetProperties()) {
     Type propType = prop.PropertyType,
          nullType = Nullable.GetUnderlyingType(propType);

     if(nullType != null) {
         // special code for handling Nullable<T> properties;
         // note nullType now holds the T
     } else {
         // code for handling other properties
     }
}

Ответ 3

Его для, когда вы не знаете его Int32.

Пример:

    public Type GetNullableUnderlyingType<T>(Nullable<T> obj) 
        where T : struct
    {
        return Nullable.GetUnderlyingType(typeof(Nullable<T>));
    }

Здесь вы можете передать любой объект Nullable и получить его, чтобы вернуть его базовый тип.

Ответ 4

Когда вы пишете int?, как будто вы написали Nullable<int>. Я думаю, что тип, который вы ищете.

Ответ 5

В основном это для решения общего метода:: например.

public static void SomeMethod<T>(T argument)
{
     if(Nullable.GetUnderlyingType(typeof(T) != null)
     {
             /* special case for nullable code go here */
     }
     else
     {
            /* Do something else T isn't nullable */
     }
}

Важно знать это, так как некоторые вещи, которые очень дешевы, могут быть невероятно дорогими в nullable. Например, if(argument == null) обычно супер дешево, но когда это делается в общем методе на Nullable<T>, принудительно вводится argument для получения нулевой ссылки. Лучше всего использовать EqualityComparer<T>.Default, который замедлит все остальное, но делает его недействительным.