C# 如果强制转换null,为什么Convert.ToString(null)返回不同的值?

C# 如果强制转换null,为什么Convert.ToString(null)返回不同的值?,c#,.net,C#,.net,返回 Convert.ToString(null) Convert.ToString(null as object) 如我所料 但是 返回 Convert.ToString(null) Convert.ToString(null as object) 为什么这些不同?这里有两个ToString的重载 "" C#编译器本质上是试图选择最具体的重载来处理输入。null值可转换为任何引用类型。在这种情况下,string比object更具体,因此它将被选为赢家 在null as object中

返回

Convert.ToString(null)
Convert.ToString(null as object)
如我所料

但是

返回

Convert.ToString(null)
Convert.ToString(null as object)

为什么这些不同?

这里有两个
ToString
的重载

""
C#编译器本质上是试图选择最具体的重载来处理输入。
null
值可转换为任何引用类型。在这种情况下,
string
object
更具体,因此它将被选为赢家

null as object
中,您将表达式的类型固化为
object
。这意味着它不再与
字符串
重载兼容,编译器选择
对象
重载,因为它是唯一剩下的兼容对象

C语言规范的第7.4.3节中详细介绍了这种打破僵局的方法。下面的答案是:“
Convert.ToString(string)
为什么返回null,但是
Convert.ToString(object)
return
string.Empty

答案是…因为你说:

ToString(string)返回“指定的字符串实例;未执行任何实际转换。”

Convert.ToString(对象)返回“值的字符串表示形式,如果值为null,则返回string.Empty。”

编辑: 至于这是否是一个“规范中的错误”、“非常糟糕的API设计”、“为什么要这样指定它”等等,我将尝试一下为什么我不认为这是一个大问题的一些基本原理

  • System.Convert
    具有将每个基本类型转换为自身的方法。这很奇怪-因为不需要或不可能进行转换,所以方法最终只返回参数<代码>转换。ToString(字符串)的行为与此相同。我假定这些是用于代码生成场景的
  • Convert.ToString(object)
    传递时有3个选项
    null
    。抛出、返回null或返回string.Empty。抛出将是不好的——假设它们用于生成的代码,情况就更糟了。返回null需要调用者执行null检查——同样,在生成的代码中,这不是一个很好的选择。返回字符串.Empty似乎是一个合理的选择。
    System.Convert的其余部分处理具有默认值的值类型
  • 返回null是否更“正确”还有争议,但string.Empty肯定更有用。更改
    Convert.ToString(string)
    意味着违反“无实际转换”规则。由于
    System.Convert
    是一个静态实用程序类,因此每个方法在逻辑上都可以视为自己的方法。现实世界中很少有这种行为会“令人惊讶”,所以让可用性战胜(可能的)正确性吧

  • 好啊所以它使用一个重载而不是另一个。有道理。但是两个重载不应该返回相同的东西吗+1顺便说一句。@JohnMacIntyre-这取决于开发团队,而不是编译器。@JohnMacIntyre如果你看一下
    Convert.ToString(string)
    的实现,它只是一个标识函数,而
    Convert.ToString(object)
    实际上走了一条更难走的路。乍一看,我同意他们应该返回相同的结果,但BCL的可转换层不是我非常熟悉的东西,可能有一个很好的原因造成这种差异(尽管我很怀疑),我来这里是为了寻找如何将空对象转换为空字符串。其他搜索者的答案是
    (string)null
    ,或者如果您的对象被称为o,那么
    (string)o
    可以公平地说这是规范中的一个bug吗?这并不能回答为什么会这样。说它的行为是这样的,因为有文件证明它的行为是重复的。@JohnMacIntyre我可以公平地说,这是非常糟糕的API设计。@CodeInChaos-不是重复的,除非您假设文档是基于BCL开发后可观察到的行为编写的。我认为这是一个奇怪的假设。瞧,它不是“有文件证明它会这样做”,而是“有文件证明它会这样做”——也就是说,它是“指定要这样做”。它只是把问题转移到“为什么指定要这样做”