Что такое использование 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
isfalse
, ссылка на объект присваиваетсяnull
вместо боксаесли объект не равен null -- if
HasValue
istrue
-- затем происходит бокс, но только базовый тип, на котором основан объект 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 не страдать.