Различные способы проверить, является ли тип обнуляемым? - PullRequest
7 голосов
/ 16 января 2012

Вот условие, которое я использовал, чтобы определить, имеем ли мы дело с Обнуляемым Типом:

System.Nullable.GetUnderlyingType(itemType) != null

и вот код моего товарища по команде:

itemType.IsGenericType && itemType.GetGenericTypeDefinition() == typeof(Nullable<>)

На самом деле мы не нашли случая, когда один вернет true, а другой false (или наоборот), но являются ли эти 2 фрагмента строго эквивалентными?

Ответы [ 5 ]

4 голосов
/ 16 января 2012

С MSDN для метода Nullable.GetUnderlyingType :

Аргумент типа параметра nullableType, если параметр nullableType является закрытым универсальным обнуляемым типом;в противном случае - null.

Итак, да, безопасно использовать предыдущую версию.

Декомпилировано из GetUnderlyingType:

public static Type GetUnderlyingType(Type nullableType)
{
  if (nullableType == null)
    throw new ArgumentNullException("nullableType");
  Type type = (Type) null;
  if (nullableType.IsGenericType && !nullableType.IsGenericTypeDefinition && nullableType.GetGenericTypeDefinition() == typeof (Nullable<>))
    type = nullableType.GetGenericArguments()[0];
  return type;
}
1 голос
/ 16 января 2012

Код вашего партнера по команде в порядке , как указано в документации MSDN (отрывок): Используйте следующий код, чтобы определить, представляет ли объект Type тип Nullable. Помните, что этот код всегда возвращает false, если объект Type был возвращен при вызове GetType.

if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) {…}

объяснено по ссылке ниже MSDN:

http://msdn.microsoft.com/en-us/library/ms366789.aspx

Более того, аналогичная дискуссия проводится в этом SO QA:

Как проверить, можно ли обнулить объект?

1 голос
/ 16 января 2012

Эти 2 фрагмента не полностью эквивалентны.
Вот тестовый пример, который возвращает разные значения для каждого фрагмента:

Type t = typeof(Nullable<>);

bool c1 = Nullable.GetUnderlyingType(t) != null; //false
bool c2 = t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>); //true

Таким образом, метод Nullable.GetUnderlyingType более безопасен, потому что его реализация уже включает проверку следующего теста:

public static Type GetUnderlyingType(Type nullableType) {
    if (nullableType == null) 
        throw new ArgumentNullException("nullableType");
    Type type = null;
    if ((nullableType.IsGenericType && !nullableType.IsGenericTypeDefinition)
        && (nullableType.GetGenericTypeDefinition() == typeof(Nullable<>))) {
        type = nullableType.GetGenericArguments()[0];
    }
    return type;
}
0 голосов
/ 16 января 2012

dotPeek показывает это:

public static Type GetUnderlyingType(Type nullableType)
{
  if (nullableType == null)
    throw new ArgumentNullException("nullableType");
  Type type = (Type) null;
  if (nullableType.IsGenericType && !nullableType.IsGenericTypeDefinition && object.ReferenceEquals((object) nullableType.GetGenericTypeDefinition(), (object) typeof (Nullable<>)))
    type = nullableType.GetGenericArguments()[0];
  return type;
}

Единственное отличие, которое я вижу, состоит в том, что itemType само по себе является общим, т.е.typeof (List<>), он потерпит неудачу.И ваш немного медленнее, потому что он должен найти базовый тип.

0 голосов
/ 16 января 2012

Каждый раз, когда проверял, является ли тип обнуляемым, я всегда использовал второй опубликованный вами метод:

itemType.IsGenericType && itemType.GetGenericTypeDefinition() == typeof(Nullable<>) 

У меня не было проблем с этим!

С уважением,

...