为什么.ToString()在空值的可空int上工作正常时,空string上的.ToString()会导致null错误?
selectedItem
有两个字段:
-
int? _cost
-
string _serialNumber
在这个例子中, _cost
和_serialNumber
是两个null。 我正在阅读selectedItem
的字段通过它们的属性,并填充文本框的值,当…
TextBox1.Text = selectedItem.Cost.ToString(); //no error TextBox2.Text = selectedItem.SerialNumber.ToString(); //error
我明白, SerialNumber.ToString()
是多余的(因为它已经是一个string),但我不明白为什么这会导致此exception:
可为空的对象必须有一个值。
-
int? _cost
int? _cost
是可空的,并没有价值,但它并没有给我例外。 -
string _serialNumber
是可为空的,并没有一个值,但它确实给我例外。
这个问题就涉及到了,这个家伙本质上是要求同样的事情,但是没有指定的答案,而且这也不能解释为什么一个可为空的int
? 例如,我可以在可空的int上使用.ToString()
,但不能在空string上使用?
由于string
types的null
实际上指向什么都没有,内存中没有任何对象。
但是int?
即使值设置为null
types(可为空)仍然指向某个对象。
如果您阅读Jeffrey Richter的“通过C#的CLR”,您会发现可空types只是具有一些封装逻辑的常见types的外观类,以便使用空值更方便工作。
检查MSDN了解可空types。
Nullable<int>
是一个struct
,不能真的为null。 所以调用“null”结构的方法仍然有效。
有一些“编译器魔术”,使_cost == null
有效的expression式。
int?
实际上并不是一个对象,但它是一个Nullable<int>
对象。
所以当你声明int? _Cost
int? _Cost
,你实际上声明Nullable<int> _Cost
和Nullable<int> _Cost
的属性是undefined
的_Cost
对象本身。
它实际上是一个语法糖,可以轻松地使用
int
,bool
或decimal
等non nullable
types。
根据MSDN :
语法
T?
是System.Nullable<T>
简写,其中T
是一个值types。 这两种forms是可以互换的。
一个string是一个引用types,但一个可为空的int是一个值types。 这里是一个很好的讨论http://www.albahari.com/valuevsreftypes.aspx的差异。;
Nullable实际上是一个暴露两个属性的结构:HasValue和Value。 如果你这样做,你会得到你的错误:
int? i = null; i.Value.ToString()
为了检查你的int是否? 有一个值可以访问i.HasValue
我认为原因是,当编译器遇到一个原始数据types时,它将其包装到相应的对象中。 toString()方法调用只是一个间接调用(包装然后调用方法),在那里处理exception。 而在String的情况下,我们直接调用该方法。 当指向一个null时,该方法抛出exception。
原因很简单。 int?
或Nullable<int>
是一个结构或一个值types , 它永远不能为null 。
那么当我们做什么时呢
int? _cost = null;
_cost
将有两个字段Value
和HasValue
,当我们分配null
为_cost
它的HasValue
标志将被设置为false
, Value
字段将被分配default(T)
的情况下int?
它会0
。
现在,当我们在_cost
上调用ToString
时, Nullable<T>
有一个ToString
的覆盖定义,如果我们看一下微软提供的Source Reference就可以实现:
public override string ToString() { return HasValue ? value.ToString() : ""; }
因此它返回一个空string,因为_cost
被赋值为null
。
现在来的string _serialNumber
的情况。 作为string
它是一个引用types,它可以完全保留null
。 如果它保持为null
那么调用ToString
就会产生Null引用exception。
您可能会看到: 值types和引用types – MSDN
TextBox2.Text = selectedItem.SerialNumber.ToString(); //error
yiels错误,因为它的调用函数ToString()是System.String的成员。 这个函数返回这个System.String的实例; 没有执行实际的转换。 而且,String是一个引用types。 引用types包含指向保存数据的另一个内存位置的指针。
TextBox1.Text = selectedItem.Cost.ToString(); //no error
不会产生任何错误,因为它正在调用函数ToString() ,它是System.Integer的成员。 此函数将此实例的数值转换为其等效的string表示forms。 另外,Integer是一个值types。 数据types是一个值types,如果它保存在自己的内存分配的数据。
相同的函数名称ToString()但执行不同的任务。
String.ToString方法
Int32.ToString方法
值types和引用types