Jar*_*Par 142

这里有2个重载ToString发挥作用

Convert.ToString(object o);
Convert.ToString(string s);
Run Code Online (Sandbox Code Playgroud)

C#编译器本质上试图选择最适合输入的特定重载.甲null值转换为任何引用类型.在这种情况下string更具体object,因此它将被选为胜利者.

null as object你已经将表达式的类型固化为object.这意味着它不再与string重载兼容,并且编译器会选择object重载,因为它是剩余的唯一兼容的.

C#语言规范的第7.4.3节介绍了这种打破这种打破方式的真正细节.

  • 好.所以它使用一个重载而不是另一个.说得通.但是,两个重载都不应该返回相同的东西吗?+1顺便说一句. (15认同)
  • @JohnMacIntyre如果你看一下`Convert.ToString(string)`的实现,它只是一个身份函数,而`Convert.ToString(object)`实际上是一个更难遵循的路径.一眼我会同意他们应该返回相同的但是BCL的可转换层不是我非常了解的东西,而且可能存在差异的充分理由(我虽然持怀疑态度) (8认同)
  • @JohnMacIntyre - 这取决于开发团队而不是编译器. (2认同)

Mar*_*ett 65

JaredPar的优秀重载解析答案之后 - 问题仍然是"为什么会Convert.ToString(string)返回null,但Convert.ToString(object)返回string.Empty"?

答案就是......因为文档说的是这样的:

Convert.ToString(string)返回"指定的字符串实例;不执行实际转换."

Convert.ToString(object)返回"value的字符串表示形式,如果value为null,则返回String.Empty".

编辑:至于这是否是"规范中的错误","非常糟糕的API设计","为什么它被指定为这样"等等 - 我会考虑一些理由为什么我看不到这很重要.

  1. System.Convert有将每种基本类型转换为自身的方法.这很奇怪 - 因为不需要或不可能进行转换,所以方法最终只返回参数.Convert.ToString(string)表现相同.我认为这些是代码生成场景.
  2. Convert.ToString(object)通过时有3个选择null.抛出,返回null或返回string.Empty.抛出会很糟糕 - 假设这些用于生成代码的假设是双倍的.返回null需要您的调用者进行空检查 - 再次,在生成的代码中不是一个很好的选择.返回string.Empty似乎是一个合理的选择.其余的System.Convert处理值类型 - 具有默认值.
  3. 返回null是否更"正确"是有争议的,但string.Empty肯定更有用.改变Convert.ToString(string)意味着打破"无实际转换"规则.由于System.Convert是静态实用程序类,因此每个方法都可以在逻辑上视为自己的方法.现实世界的情况很少,这种行为应该是"令人惊讶的",所以让可用性赢得(可能)正确性.

  • 它只是将问题转移到"为什么它被指定为表现得像这样" (8认同)
  • @CodeInChaos - 不是重言式,除非你假设在BCL开发之后,文档是基于可观察的行为编写的.我认为这是一个奇怪的假设.IOW,它不是"记录下来,表现得像这样",它"记录下它*将*表现得像这样" - 即,"*指定*表现得像这样". (7认同)
  • 这不能回答为什么会这样.说它的行为就像这样,因为它的记录表明这样做是同义反复的. (3认同)
  • @JohnMacIntyre IMO公平地说它是非常糟糕的API设计. (2认同)
  • 值得注意的是,“Convert.ToString”实际上在技术上可以从“object”重载返回“null”。指定当输入为“null”时,它不返回“null”,但当输入“非”“null”时,它会调用输入自己的“.ToString()”方法。可以重写该方法以返回“null”。这可能不是一个好主意,但这样做不会违反任何运行时规则。使用 `class ToStringNull { public override string ToString() { return null; } }`,你会从 `Convert.ToString(new ToStringNull())` 返回一个 `null`。 (2认同)