Как определить, является ли ненулевой объект структурой Nullable? - PullRequest
5 голосов
/ 12 мая 2011

Есть ли что-нибудь, чтобы узнать это?

Я нашел один пост, в котором задавался очень похожий вопрос на Как проверить, можно ли обнулять объект? Ответ объясняет, как определить, можно ли обнулять объект , если есть доступ к универсальному. Введите параметр . Это достигается с помощью Nullabe.GetUnderlyingType(typeof(T)). Однако, если у вас есть только объект, и он не является нулевым, можете ли вы определить, является ли он на самом деле Nullable ValueType?

Другими словами, есть ли лучший способ, чем индивидуальная проверка каждого возможного типа значения, допускающего значение NULL, для определения, является ли штучная структура структурой типа значения?

void Main(){
    Console.WriteLine(Code.IsNullableStruct(Code.BoxedNullable));
} 


public static class Code{
    private static readonly int? _nullableInteger = 43;

    public static bool IsNullableStruct(object obj){
                  if(obj == null) throw new ArgumentNullException("obj");
                  if(!obj.GetType().IsValueType) return false;
                  return IsNullablePrimitive(obj);
            }
    public static bool IsNullablePrimitive(object obj){
         return obj is byte? || obj is sbyte? || obj is short? || obj is ushort? || obj is int? || obj is uint? || obj is long? || obj is ulong? || obj is float? || obj is double? || obj is char? || obj is decimal? || obj is bool? || obj is DateTime? || obj is TimeSpan?;
    }

    public static object BoxedNullable{
        get{ return _nullableInteger; }
    }
}

-

Обновление

Я нашел эту статью на MSDN , и там говорится, что вы не можете определить, является ли тип структурой Nullable, с помощью вызова GetType().

-

Обновление # 2

Очевидно, что предложенный мной метод тоже не работает, потому что int x = 4; Console.WriteLine(x is int?); - True. (См. Комментарий)

Ответы [ 4 ]

4 голосов
/ 12 мая 2011

Цитирую комментарий Джона Скита в связанном вопросе:

нет такого понятия, как обнуляемый тип в штучной упаковке - Nullable упаковывается в пустую ссылку или в штучную упаковку int

так что в вашем примере программы к моменту времени BoxedNullable передается в IsNullableStruct, который принимает object в качестве параметра, значение уже в штучной упаковке 43, больше ничего не обнуляется. По иронии судьбы x is int? - это true для любого int, обнуляемого или иного, так что это только добавляет путаницы.

В любом случае, ваш первоначальный вопрос, согласно комментарию Джона, кажется, не имеет смысла.

1 голос
/ 12 мая 2011

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

Обратите внимание, что ваш IsNullablePrimitive фактически вернет true, если вы передадите ему не-Nullable int!

0 голосов
/ 12 мая 2011

Nullable <> - особый класс.Когда вы пытаетесь проверить или скопировать Nullable <>, он преобразуется / помещается в «null» или в тип значения, которое он содержит.Вызов GetType () фактически вызовет исключение, если у вашего Nullable <> нет значения, или в лучшем случае вернет базовый тип.Подмена происходит на самом низком уровне.Вы не можете идентифицировать Nullable <> любым кошерным способом.

0 голосов
/ 12 мая 2011

Да, вы просто проверяете общее определение:

protected bool IsNullableType(Type type)
{
    if(!type.IsGeneric)
        return false;

    return type.GetGenericDefinition() == typeof(Nullable<>);
}

Фактически эти утверждения совпадают:

var type = typeof(Nullable<>);
var type2 = new Nullable<int>().GetType().GetGenericDefinition();
...