71

selectedItem有两个字段:

  • int? _cost
  • string _serialNumber

在这个例子中,_costand _serialNumberofselectedItem都是空的。我正在阅读selectedItem它们的属性字段,并用它们的值填充文本框,当...

TextBox1.Text = selectedItem.Cost.ToString(); //no error
TextBox2.Text = selectedItem.SerialNumber.ToString(); //error

我知道这SerialNumber.ToString()是多余的(因为它已经是一个字符串),但我不明白为什么这会导致这个异常:

可空对象必须有一个值。

  • int? _cost可以为空,并且没有值,但它没有给我例外。
  • string _serialNumber可以为空,并且没有值,但它确实给了我例外。

这个问题涉及到它,这家伙本质上是在问同样的事情,但是没有指定答案,也没有解释为什么可以为空int?例如,我可以.ToString()在可为空的 int 上使用但不能在空字符串上使用吗?

4

8 回答 8

91

因为stringtypenull真的没有指向任何东西,所以内存中没有任何对象。
但是int?type(nullable) 即使值设置为null仍然指向某个对象。
如果您阅读 Jeffrey Richter 的“CLR via C#”,您会发现可空类型只是具有一些封装逻辑的常见类型的外观类,以便更方便地使用 DB null。

检查msdn以了解可空类型。

于 2012-07-12T07:25:02.643 回答
34

ANullable<int>是 astruct并且不能真正为空。因此,对“null”结构的方法调用仍然有效。

有一些“编译器魔法”可以_cost == null生成有效的表达式。

于 2012-07-12T07:24:05.357 回答
15

int?实际上它本身并不是一个对象,但它是一个Nullable<int>对象。

因此,当您声明时int? _Cost,您实际上是在声明,Nullable<int> _Cost并且的属性_Cost.Value不是对象本身。undefined_Cost

它实际上是一种语法糖,可以轻松使用 ,non nullable等类型。intbooldecimal

根据MSDN

语法T?是 的简写System.Nullable<T>,其中T是值类型。这两种形式可以互换。

于 2012-07-12T07:28:35.437 回答
4

字符串是引用类型,但可为空的 int 是值类型。这是对差异http://www.albahari.com/valuevsreftypes.aspx的很好讨论。

于 2012-07-12T07:31:07.583 回答
3

Nullable 实际上是一个公开两个属性的结构:HasValue 和 Value。如果你这样做,你会得到你的错误:

int? i = null;
i.Value.ToString()

为了检查你的int?具有您可以访问的值i.HasValue

于 2012-07-12T07:24:45.977 回答
1

我认为原因是,当编译器遇到原始数据类型时,它会将其包装到相应的对象中。toString() 方法调用在这里只是间接调用(包装然后调用方法),异常在那里处理。而在 String 的情况下,我们直接调用该方法。当指向 null 时,该方法会引发异常。

于 2012-07-12T07:30:48.840 回答
1

原因很简单。int?orNullable<int>structvalue 类型它永远不能为 null

那么当我们这样做时会发生什么:

int? _cost = null;

_cost将有两个字段ValueHasValue当我们分配null_cost它的 HasValue标志时,它将被设置为false并且该Value字段将被分配default(T)以防int?万一0

现在,当我们调用ToString_costNullable<T>有一个 的覆盖定义ToString,如果我们查看Microsoft 提供的 Source Reference,它的实现如下:

public override string ToString() {
    return HasValue ? value.ToString() : "";
}

因此它返回一个空字符串,因为_costis assigned null

现在是string _serialNumber. 因为string它是一个引用类型,它可以纯粹地持有null。如果它保持,null那么调用ToString它会按预期产生空引用异常。

您可能会看到:值类型和引用类型 - MSDN

于 2014-06-25T20:14:16.680 回答
0
TextBox2.Text = selectedItem.SerialNumber.ToString(); //error

产生错误,因为它正在调用System.String成员的函数ToString()。此函数返回此 System.String 实例;不执行实际转换。此外,String 是一种引用类型。引用类型包含指向另一个保存数据的内存位置的指针。

TextBox1.Text = selectedItem.Cost.ToString(); //no error

不会产生错误,因为它正在调用 作为System.Integer成员的函数ToString()。此函数将此实例的数值转换为其等效的字符串表示形式。此外,整数是一种值类型。如果数据类型将数据保存在自己的内存分配中,则该数据类型是值类型。

相同的函数名称 ToString() 但执行不同的任务。

String.ToString 方法

Int32.ToString 方法

值类型和引用类型

于 2012-07-12T12:05:17.553 回答