Какой смысл использовать Nullable.GetUnderlyingType, если typeof (int?) Является Int32? - PullRequest
13 голосов
/ 23 декабря 2010

почему typeof int? и Int32

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

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

Ответы [ 5 ]

23 голосов
/ 23 декабря 2010

Вызов 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, помещаются в квадрат, только если объект ненулевой.Если HasValue равно false, ссылка на объект присваивается null вместо бокса

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

11 голосов
/ 23 декабря 2010

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

int? x = 1;

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

Type tupe = x.GetType();

- это вызов невиртуального метода в object, который не (и не может быть) переопределен - поэтому это операция boxing 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
     }
}
4 голосов
/ 23 декабря 2010

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

Пример:

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

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

1 голос
/ 23 декабря 2010

В основном это для работы с универсальным методом: например,

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 не страдает.

1 голос
/ 23 декабря 2010

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

...