Что такое использование Nullable.GetUnderlyingType, если typeof(int?) это типа int32?

Почему typeof int? an Int32

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

если это нормально, то какой смысл Nullable.GetUnderlyingType?

5 ответов


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

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

С Nullable содержащих null будет в коробке null следующее вызовет исключение:

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

цитата MSDN по боксу Nullable типов:

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

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


этот пример немного смутило, потому что:

int? x = 1;

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

Type tupe = x.GetType();

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

  • если он пуст, он вставляет вnull
  • если он имеет значение, то стоимостью боксировал и вернулся

то есть

int? x = 1;
int y = 1;

box to ровно то же самое.

таким образом, вы передаете typeof(int) to 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
     }
}

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

пример:

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

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


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


главным образом его для работы с общим методом:: например,

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 что замедлит все остальное, но делает nullable не страдать.