GetType在Nullable布尔值上

时间:2016-07-24 11:51:45

标签: c# null boolean

当我在Microsoft MSDN上发现这篇文章时,我正在研究可空的bool

How to: Identify a Nullable Type (C# Programming Guide)

  

您可以使用C#typeof运算符创建一个表示Nullable类型的Type对象。

所以我尝试用可空的bool进行检查:

Console.Write(typeof(bool?)); //System.Nullable`1[System.Boolean]

MSDN上的文章说

  

您还可以使用System.Reflection命名空间的类和方法来生成表示Nullable类型的Type对象。但是,如果您尝试通过使用GetType方法或is运算符在运行时从Nullable变量获取类型信息,则结果是一个Type对象,它表示基础类型,而不是Nullable类型本身。

     

在Nullable类型上调用GetType会导致在将类型隐式转换为Object时执行装箱操作。 因此,GetType始终返回一个Type对象,该对象表示基础类型,而不是Nullable类型。

如果这是真的,我希望从.GetType()获得相同的结果,无论我使用可空的bool还是普通的bool。但事实并非如此:

    bool a = new bool();
    Console.Write(a.GetType()); //Prints System.Boolean

    bool? b = new bool?();
    Console.Write(b.GetType()); //Exception!

发生的例外情况:

  

未处理的类型' System.NullReferenceException'发生在BoolTest.exe

     

附加信息:未将对象引用设置为对象的实例。

但是对象引用设置为对象的实例。可能是造成此错误的原因是什么?

2 个答案:

答案 0 :(得分:5)

您的实际问题似乎是:

  

通过使用默认构造函数(例如Nullable<T>)将bool? b = new bool?();初始化为其默认值,为什么访问b的成员(例如GetType())会抛出{{} 1}? NullReferenceException不会始终返回值,因此new不能真正b吗?

嗯,是的,不是。 null有点特别。来自C#规范:

  

4.1.10可空类型

     

[...]

     

可空类型T的实例?有两个公共只读属性:

     
      
  • 类型为bool的HasValue属性
  •   
  • 类型为T
  • 的Value属性   
     

HasValue为true的实例被称为非null。非null实例包含已知值,Value返回该值。    HasValue为false的实例被称为null。 null实例具有未定义的值。尝试读取null实例的值会导致抛出System.InvalidOperationException。

所以是的,Nullable<T>会返回一个实例:你只能打bool? b = new bool?();。由于它返回HasValue,因此您无法对该实例执行其他操作。

然后是下一个相关部分:

  

4.3.1拳击转化

     

如果它是空值(HasValue为false),则对可空类型的值进行装箱会产生空引用

MSDN: Boxing Nullable Types (C# Programming Guide)中也解释了这一点:

  

如果对象为非null,则仅基于可空类型的对象进行装箱。如果HasValue为false,则将对象引用分配为null而不是装箱

进一步了解规范:

  

11.3.5装箱和拆箱

     

当结构类型覆盖从System.Object继承的虚方法(例如Equals,GetHashCode或ToString)时,通过struct类型的实例调用虚方法不会导致发生装箱。

false未被GetType()覆盖,因此将发生装箱。当您在结构上调用Nullable<T>或任何未重写的方法时,在调用该方法之前,结构将被装箱到对象。在空GetType()的情况下,该装箱操作的结果将是Nullable<T>。因此例外。

另见Does calling a method on a value type result in boxing in .NET?

所以,回答你的问题:

  • (object)null null,它包含bNullable<bool>表示HasValue
  • 在其上调用未覆盖的false方法,会导致GetType()结构框被设置为访问基础方法Nullable<bool>
  • 这个装箱操作实际上没有框,只是返回object.GetType()
  • 最后,您正在调用(object)null,这会引发您遇到的((object)null).GetType()

如果您实际上正在寻找可以返回任何变量类型的代码,即使是null NullReferenceException,也可以使用以下内容:

Nullable<T>

然后你可以这样打电话:

Type GetType<T>(T obj) 
{ 
    return typeof(T); 
}

答案 1 :(得分:4)

您正在Product - Price - SalesDate ProdA - 10 - 1/1/2016 ProdB - 20 - 1/2/2016 ProdA - 100 - 1/3/2016 ProdB - 20 - 1/4/2016 ProdB - 21 - 1/5/2016 ProdA - 11 - 1/6/2016 参考号上调用GetType(将Nullable类型装入无值的结果)。

NULL相当于bool? b = new bool?();

尝试此操作以获得正确的结果:

bool? b = null;

文档意味着如果您在具有值(非空)的bool? b = new bool?(false); Console.Write(b.GetType()); // System.Boolean 对象上成功调用GetType()。您获得的基础类型为Nullable。但是你不能使用System.Boolean引用调用任何方法,这是应用于任何引用类型的一般规则。

要清除NULL= null之间的等值点,请检查此Fiddle。两者都生成相同的IL:

new bool?()

IL_0001:  ldloca.s   V_0
IL_0003:  initobj    valuetype [mscorlib]System.Nullable`1<bool>