为什么.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上使用?

由于stringtypes的null实际上指向什么都没有,内存中没有任何对象。
但是int? 即使值设置为nulltypes(可为空)仍然指向某个对象。
如果您阅读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> _CostNullable<int> _Cost的属性是undefined_Cost对象本身。

它实际上是一个语法糖,可以轻松地使用intbooldecimalnon nullabletypes。

根据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将有两个字段ValueHasValue ,当我们分配null_cost它的HasValue标志将被设置为falseValue字段将被分配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