如何确定非null对象是否为Nullable结构?

时间:2011-05-12 02:55:12

标签: c# reflection c#-4.0 nullable value-type

反正知道这个吗?

我发现一篇帖子在How to check if an object is nullable?问了一个非常相似的问题。答案解释了如何确定某个对象是否可为空如果可以访问通用类型参数。这是通过使用Nullabe.GetUnderlyingType(typeof(T))来完成的。但是,如果您只有一个对象并且它不为null,您能否确定它是否实际上是Nullable ValueType?

换句话说,有没有比单独检查每个可能的可空值类型更好的方法来确定盒装结构是否是值类型?

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; }
    }
}

-

更新

我找到了this article at MSDN,它说你无法通过调用GetType()来确定某个类型是否为Nullable结构。

-

更新#2

显然我建议的方法不起作用,因为int x = 4; Console.WriteLine(x is int?);为True。 (见评论)

4 个答案:

答案 0 :(得分:4)

引用Jon Skeet对您链接的问题的评论:

  

没有盒装可空类型 - Nullable被装箱到空引用或盒装int

因此,在您的示例程序中,当BoxedNullable传递给IsNullableStruct时,object作为参数,该值已经是一个装箱43,不再任何可以为空的东西。具有讽刺意味的是,x is int?对于任何true都是int,可以为空或者以其他方式存在,因此只会增加混淆。

在任何情况下,根据Jon的评论,你的原始问题似乎没有意义。

答案 1 :(得分:1)

当你打开一个可空的时候,它实际上是它的底层类型。可空< INT>将变成一个盒装的int。无法判断盒装值类型的来源是否为Nullable。

请注意,如果您将IsNullablePrimitive传递给非Nullable int,那么{{1}}实际上将返回true!

答案 2 :(得分:0)

可空<>是一个特殊的课程。当您尝试检查或复制Nullable<>它被转换/装箱为'null'或它包含的值类型。如果您的Nullable<>调用GetType()实际上会抛出异常没有值,或者最多返回基础类型。欺骗发生在最低级别。您无法识别Nullable<>通过任何犹太教手段。

答案 3 :(得分:-1)

是的,您只需检查通用定义:

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();