C # Reflection: Как получить тип Nullable <int>? - PullRequest
27 голосов
/ 18 декабря 2011

Что я хочу сделать, это примерно так:

switch( myObject.GetType().GetProperty( "id") )
{
    case ??: 
        // when Nullable<Int32>, do this
    case ??:
        // when string, do this
    case ??:
        // when Nullable<bool>, do this

Какой путь в object.GetType () будет содержать строковое имя типа данных, которое я могу сравнить с помощью оператора case? Мне нужно знать тип, чтобы у меня был один из множества Convert.ToInt32 (string), который будет устанавливать значение myObject с помощью Reflection.

Ответы [ 5 ]

61 голосов
/ 18 декабря 2011

Я использовал следующий тип кода, чтобы проверить, является ли тип обнуляемым и получить фактический тип:

if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
{
    return Nullable.GetUnderlyingType(type);
}

Если тип, например, обнуляется, этот код возвращает часть intтип).Если вам просто нужно преобразовать объект в определенный тип, вы можете использовать метод System.Convert.ChangeType.

18 голосов
/ 19 декабря 2011

Вопрос очень запутанный.Является ли myObject объектом, который может быть обнуляемым int?Или свойство id может иметь тип nullable int?

Если первое, на ваш вопрос нельзя ответить, поскольку оно предполагает ложь.Там нет такого понятия, как упакованный в Nullable Int.Я отмечаю, что все ответы, которые предлагают if (myobject.GetType() == typeof(int?)), являются поэтому неправильными;условие никогда не будет истинным.

Когда вы преобразуете обнуляемое int в объект, оно либо становится нулевой ссылкой (если у обнуляемого int нет значения), либо оно становится упакованным int.Невозможно определить, содержит ли объект обнуляемое значение типа int, потому что объект никогда не содержит значения типа NULL.

Если последнее, сравните тип свойства с typeof(int?).Вы не можете использовать переключатель;только константы могут использоваться для случаев переключения, а типы не являются константами.

Все это говорит о том, что это плохой запах кода.Почему вы используете отражение в первую очередь?

12 голосов
/ 18 декабря 2011

Обновление: похоже, C # 7 будет поддерживать включение Type s, как пытался сделать тот, кто задавал этот вопрос.Это немного отличается, так что следите за синтаксическими минами.

Вам не нужно имя строки для сравнения:

if (myObject.GetType().GetProperty("id").PropertyType == typeof(Nullable<Int32>))
    // when Nullable<Int32>, do this
else if (myObject.GetType().GetProperty("id").PropertyType == typeof(string))
    // when string, do this
else if (myObject.GetType().GetProperty("id").PropertyType == typeof(Nullable<bool>))
    // when Nullable<bool>, do this
2 голосов
/ 27 января 2012

В .net экземпляры типов значений - это просто наборы битов, без информации о связанных типах.Однако для каждого типа значения, отличного от Nullable<T>, система также автоматически генерирует соответствующий тип класса, производный от System.ValueType.Существует расширяющееся преобразование из типа значения в автоматически сгенерированный тип класса и сужающее преобразование из автоматически сгенерированного типа класса в тип значения.В случае Nullable<T> нет соответствующего автоматически сгенерированного типа класса с преобразованиями в / из типа значения;вместо этого расширяющиеся преобразования существуют в обоих направлениях между Nullable<T> и типом класса, связанным с T.

Насколько я могу судить, это странное поведение было реализовано, чтобы позволить сравнения между null и пустымNullable<T> чтобы вернуть true.

0 голосов
/ 18 декабря 2011

Как сказал @ Коди Грей, если заявления, вероятно, будут лучшим способом

var t = myObject.GetType();

if (t == typeof(Nullable<int>))
{ }
else if (t == typeof(string))
{}
else if (t==typeof(Nullable<bool>))
{}
...