C# 为什么空字符串上的.ToString()会导致空错误,而.ToString()在具有空值的可空int上运行良好?

C# 为什么空字符串上的.ToString()会导致空错误,而.ToString()在具有空值的可空int上运行良好?,c#,string,null,int,nullable,C#,String,Null,Int,Nullable,selectedItem有两个字段: int_成本 string\u serialNumber 在本例中,selectedItem的\u cost和\u serialNumber均为空。我正在通过它们的属性读取selectedItem的字段,并在文本框中填入它们的值,这时 TextBox1.Text = selectedItem.Cost.ToString(); //no error TextBox2.Text = selectedItem.SerialNumber.ToString();

selectedItem
有两个字段:

  • int_成本
  • string\u serialNumber
在本例中,
selectedItem
\u cost
\u serialNumber
均为空。我正在通过它们的属性读取
selectedItem
的字段,并在文本框中填入它们的值,这时

TextBox1.Text = selectedItem.Cost.ToString(); //no error
TextBox2.Text = selectedItem.SerialNumber.ToString(); //error
我知道
SerialNumber.ToString()
是多余的(因为它已经是一个字符串),但我不明白为什么会出现这种异常:

可为null的对象必须有一个值

  • int_cost
    可以为null,并且没有值,但它不会给我异常
  • string\u serialNumber
    可以为空,并且没有值,但是它会给我一个异常
这涉及到它,这家伙本质上是在问同样的问题,但是没有指定的答案,而且它也没有解释为什么一个可为null的
int
?例如,我可以在可为null的int上使用
.ToString()
,但不能在null字符串上使用吗?

可为null的
是一个
结构,不能真正为null。因此,对“null”结构的方法调用仍然有效


有一些“编译器魔法”使
\u cost==null
成为一个有效的表达式。

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

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

为了检查你的int是否正确?有一个值你可以访问
i.HasValue

,因为
string
type的
null
实际上没有指向任何对象,所以内存中没有任何对象。
但是
int?
type(null)即使值设置为
null
仍然指向某个对象。
如果你阅读杰弗里里克特的“CLR via C#”您将发现,可为null的类型只是带有一些封装逻辑的普通类型的门面类,以便更方便地使用DB null


检查以了解可为空的类型。

int?
本身实际上不是一个对象,但它是一个可为空的
对象

那么当你声明
int_Cost
,您实际上是在声明
可空的\u Cost
,而
\u Cost.Value的属性是
未定义的
而不是
\u Cost
对象本身

实际上,很容易使用
不可空
类型,如
int
bool
decimal
,这是一种语法上的甜点

根据:

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


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

字符串是引用类型,但可为null的int是值类型。这里是一个很好的差异讨论

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

TextBox1.Text = selectedItem.Cost.ToString(); //no error
不会产生错误,因为它正在调用属于System.Integer的函数。此函数用于将此实例的数值转换为其等效的字符串表示形式。此外,Integer是一种值类型。如果数据类型将数据保存在自己的内存分配中,那么它就是值类型

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


原因很简单
int?
或者是结构或,它永远不能为空

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

int? _cost = null;
\u cost
将有两个字段
Value
HasValue
,当我们将
null
分配给
\u cost
时,其
HasValue
标志将设置为
false
,并且
Value
字段将被分配
默认值(T)
,如果
int?
它将
设置为
0

现在,当我们在
\u cost
上调用
ToString
时,
Nullable
有一个
ToString
的覆盖定义,如果我们看一下,它的实现如下:

public override string ToString() {
    return HasValue ? value.ToString() : "";
}
因此,它返回一个空字符串,因为
\u cost
被赋值为
null

现在是
string\u serialNumber
的例子。作为
字符串
它是一个引用类型,它可以完全保持
null
。如果它保持
null
,则对其调用
ToString
,将产生预期的null引用异常


您可能会看到:

您链接到的问题完全不同。这个问题是关于
MessageBox.Show
String.Concat
如何处理
null
字符串。请注意,您使用的单词“nullable”表示两种完全不同的含义
int?
是一种值类型,称为
Nullable
,对空值有特殊处理
string
是一种引用类型(虽然有点奇怪),它的实际值可以是
null
int?
总是有一个值,它只是有一种特殊的方式来表示“我现在的行为就像
null
。”所以基本上,因为它实际上不是null,它只是假装为null?是的,基本上它是一个围绕int字段的结构,布尔符号表示这个结构是设置为int值,还是仍然单位化,这意味着零。在里面
public override string ToString() {
    return HasValue ? value.ToString() : "";
}