Как я могу определить, является ли тип объекта Nullable <T>с использованием отражения? - PullRequest
9 голосов
/ 05 октября 2010

Если у меня есть Type, есть ли какой-нибудь простой способ сказать, что он представляет тип значения, допускающий значение NULL, с помощью Reflection? В идеале что-то немного чище (и правильнее), чем:

static bool IsNullable(Type type)
{
    return type.IsValueType && type.Name.StartsWith("Nullable");
}

Ответы [ 2 ]

18 голосов
/ 05 октября 2010
type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)

Вы также можете найти Nullable.GetUnderlyingType(Type nullableType) полезным, чтобы легко получить T из typeof(Nullable<T>), который вы передаете.

7 голосов
/ 05 октября 2010

Несмотря на то, что ответ @ theCoop верный (в принципе нет ничего неправильного в размещении его кода в теле предоставленного вами метода), здесь есть несколько гигантских ошибок.

Nullable<T> обрабатывается во время выполнения как «специальный» тип, который имеет очень специфическую семантику. В частности, когда Nullable<T> в штучной упаковке:

  1. Если HasValue == true, он ведет себя так же, как T в штучной упаковке, что делает невозможным для кода нижестоящего элемента определить, был ли создан созданный объект путем помещения T в коробку или Nullable<T>. Возможна распаковка на T и Nullable<T>.
  2. Если HasValue == false, бокс просто возвращает null. Распаковка на T приведет к выбросу, распаковка на Nullable<T> будет успешной, для чего HasValue == false.

В любом случае, boxedNullableObject.GetType() не покажет, что объект был создан боксом Nullable<T>.. Я не могу думать о каком-либо другом типе значения, который демонстрирует такое странное поведение.

Например, рассмотрим:

// Output: "System.Nullable`1[System.Int32]"
Console.WriteLine(typeof(int?));


object boxedNullableInt32WithValue = new int?(0);

// Output: "System.Int32", NOT "System.Nullable`1[System.Int32]"
Console.WriteLine(boxedNullableInt32WithValue.GetType()); 


object boxedNullableInt32WithoutValue = new int?();

// NullReferenceException is thrown
Console.WriteLine(boxedNullableInt32WithoutValue.GetType()); 

Следовательно, написание метода, такого как:

public static bool IsObjectANullableT(this object obj) { ... }

действительно плохая идея.

РЕДАКТИРОВАТЬ : В другой заметке я только что понял, что есть метод каркаса, который делает то, что вам нужно, используя ту же технику, что и образец @ theCoop: Nullable.GetUnderlyingType.

Использование:

static bool IsNullable(Type type)
{
    return Nullable.GetUnderlyingType(type) != null;
}

РЕДАКТИРОВАТЬ : Только что увидел, что @TheCoop также упомянул это в своем ответе. Моя ошибка.

...