selectedItem
有两个字段:
int? _cost
string _serialNumber
在此示例中,_cost
的{{1}}和_serialNumber
均为空。我正在通过他们的属性阅读selectedItem
的字段,并在文本框中填写其值,以及......
selectedItem
我理解TextBox1.Text = selectedItem.Cost.ToString(); //no error
TextBox2.Text = selectedItem.SerialNumber.ToString(); //error
是多余的(因为它已经是一个字符串),但我不明白为什么会导致这个异常:
Nullable对象必须有值。
SerialNumber.ToString()
可以为空,并且没有值,但它没有给我例外。int? _cost
可以为空,并且没有值,但确实给我例外。这个question触及它,这个家伙基本上是在问同样的事情,但是没有指定的答案,也没有解释为什么可以为空string _serialNumber
?例如,我可以在可空int上使用int
但不能在空字符串上使用吗?
答案 0 :(得分:89)
因为string
类型的null
确实没有指向任何内容,所以内存中没有任何对象。
但int?
类型(可为空)即使值设置为{{仍然指向某个对象。
如果你读过Jeffrey Richter的“CLR via C#”,你会发现可空类型只是普通类型的外观类,带有一些封装逻辑以便使用DB null工作更方便。
检查msdn以了解可空类型。
答案 1 :(得分:32)
Nullable<int>
是struct
,实际上不能为空。因此,对“null”结构的方法调用仍然有效。
有一些“编译器魔术”使_cost == null
成为有效的表达式。
答案 2 :(得分:14)
int?
实际上并不是一个对象,但它是一个Nullable<int>
对象。
因此,当您声明int? _Cost
时,您实际上声明Nullable<int> _Cost
且_Cost.Value
的属性为undefined
而不是_Cost
对象本身。
使用
non nullable
,int
或bool
之类的decimal
类型实际上是一种语法糖。
根据MSDN:
语法
T?
是System.Nullable<T>
的简写,其中T
是值类型。这两种形式是可以互换的。
答案 3 :(得分:4)
字符串是引用类型,但可以为null的int是值类型。以下是对差异http://www.albahari.com/valuevsreftypes.aspx的良好讨论。
答案 4 :(得分:2)
Nullable实际上是一个暴露两个属性的结构:HasValue和Value。如果你这样做,你会收到错误:
int? i = null;
i.Value.ToString()
为了检查你的int?有一个值,你可以访问i.HasValue
答案 5 :(得分:1)
我认为原因是,当编译器遇到它包装它的原始数据类型时,它到相应的对象。 toString()方法调用只是一个间接调用(包装然后调用方法),并在那里处理异常。 在String的情况下,我们直接调用该方法。当指向null时,该方法抛出异常。
答案 6 :(得分:1)
原因很简单。 int?
或Nullable<int>
是结构或value type,永远不能为空。
那么当我们这样做时会发生什么:
int? _cost = null;
_cost
将有两个字段Value
和HasValue
,当我们将null
分配给_cost
时,其HasValue
标记将设置为{在false
Value
default(T)
的情况下,int?
0
字段将被分配ToString
。
现在,当我们在_cost
上致电Nullable<T>
时,ToString
的覆盖定义为public override string ToString() {
return HasValue ? value.ToString() : "";
}
,如果我们查看Microsoft's provided Source Reference,则执行方式如下:< / p>
_cost
因此它返回一个空字符串,因为null
被分配了string _serialNumber
。
现在出现string
的情况。作为null
,它是一种引用类型,它可以纯粹持有null
。如果它持有ToString
,则在其上调用{{1}}将产生预期的空引用异常。
答案 7 :(得分:0)
TextBox2.Text = selectedItem.SerialNumber.ToString(); //error
yiels错误,因为它调用函数ToString(),它是 System.String 的成员。此函数返回此System.String实例;没有执行实际转换。此外,String是引用类型。引用类型包含指向另一个保存数据的内存位置的指针。
TextBox1.Text = selectedItem.Cost.ToString(); //no error
不会产生任何错误,因为它正在调用函数ToString(),它是 System.Integer 的成员。此函数将此实例的数值转换为其等效的字符串表示形式。此外,Integer是一种值类型。如果数据类型将数据保存在自己的内存分配中,则数据类型是值类型。
相同的函数名称ToString()但执行不同的任务。