当我在Microsoft MSDN上发现这篇文章时,我正在研究可空的bool
您可以使用C#typeof运算符创建表示Nullable类型的Type对象.
所以我尝试用可空的布尔检查:
Console.Write(typeof(bool?)); //System.Nullable`1[System.Boolean]
Run Code Online (Sandbox Code Playgroud)
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!
Run Code Online (Sandbox Code Playgroud)
发生的例外情况:
BoolTest.exe中出现未处理的"System.NullReferenceException"类型异常
附加信息:未将对象引用设置为对象的实例.
但是对象引用设置为对象的实例.可能是导致此错误的原因是什么?
你正在调用GetType一个NULL引用(装箱一个没有值的可空类型的结果)。
bool? b = new bool?(); 相当于 bool? b = null;
试试这个以获得正确的结果:
bool? b = new bool?(false);
Console.Write(b.GetType()); // System.Boolean
Run Code Online (Sandbox Code Playgroud)
该文档意味着如果您GetType()成功调用Nullable具有值(非空)的对象。你得到的底层类型是System.Boolean. 但是您不能使用NULL引用调用任何方法,这是适用于任何引用类型的一般规则。
要清除= null和之间的等价点new bool?(),请检查此Fiddle。两者都生成相同的 IL:
IL_0001: ldloca.s V_0
IL_0003: initobj valuetype [mscorlib]System.Nullable`1<bool>
Run Code Online (Sandbox Code Playgroud)
和
IL_0009: ldloca.s V_1
IL_000b: initobj valuetype [mscorlib]System.Nullable`1<bool>
Run Code Online (Sandbox Code Playgroud)
你的实际问题似乎是:
Nullable<T>例如bool? b = new bool?();,通过使用其默认构造函数将a初始化为其默认值,为什么访问b的成员如GetType()throw aNullReferenceException?并不new总是返回一个值,所以b真的不是null吗?
嗯,是的,不.Nullable<T>有点特别.来自C#规范:
4.1.10可空类型
[...]
可空类型T的实例?有两个公共只读属性:
- bool类型的HasValue属性
- T类型的Value属性
HasValue为true的实例被称为非null.非null实例包含已知值,Value返回该值. HasValue为false的实例被称为null.null实例具有未定义的值.尝试读取null实例的值会导致抛出System.InvalidOperationException.
所以是的,bool? b = new bool?();确实会返回一个实例:一个你只能调用的实例HasValue.由于它返回false,你不能对该实例做很多其他事情.
然后是下一个相关部分:
4.3.1拳击转换
如果它是空值(HasValue为false),则为可空类型的值装箱会产生空引用
MSDN中也解释了这一点 :Boxing Nullable Types(C#编程指南):
如果对象为非null,则仅基于可空类型的对象进行装箱.如果HasValue为false,则将对象引用分配为null而不是装箱.
进一步了解规格:
11.3.5拳击和拆箱
当结构类型覆盖从System.Object继承的虚方法(例如Equals,GetHashCode或ToString)时,通过struct类型的实例调用虚方法不会导致发生装箱.
GetType()没有被覆盖Nullable<T>,所以拳击会发生.当您GetType()在结构上调用或任何未重写的方法时,在调用该方法之前,该结构将被装箱到一个对象.在null的情况下,Nullable<T>该装箱操作的结果将是(object)null.因此例外.
那么,回答你的问题:
b是不是空,它拥有一个Nullable<bool>带有HasValue指示false.GetType()上调用非重写方法会导致对Nullable<bool>结构进行装箱以访问基础方法object.GetType().(object)null.((object)null).GetType(),这会引发NullReferenceException你的遭遇.如果您实际上正在寻找可以返回任何变量类型的代码,甚至是null Nullable<T>,请使用以下内容:
Type GetType<T>(T obj)
{
return typeof(T);
}
Run Code Online (Sandbox Code Playgroud)
你可以这样打电话:
Console.WriteLine(GetType(b));
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2948 次 |
| 最近记录: |