【问题标题】:Under what circumstances should `object.ToString()` return null?什么情况下`object.ToString()`应该返回null?
【发布时间】:2021-02-24 12:46:39
【问题描述】:

.Net Core defines object.ToString() as public virtual string? ToString();

这意味着如下代码会引发CS8602“取消引用可能为空的引用”警告:

object t = "test";
var s = t.ToString();
Console.WriteLine(s.Length); // Warning CS8602

这很容易通过写s!.Lengtht.ToString()!; 来解决,但我的问题是:

在什么情况下从object.ToString() 的实现返回null 是正确的?


答案似乎是:“您永远不应该从 object.ToString() 返回 null”,这很公平 - 但这确实引发了另一个问题,即“在这种情况下,为什么 Microsoft 将其声明为 @ 987654335@" ?


旁白:

下面的一些 cmets 建议,因为实现可能错误地返回 null,所以返回值必须声明为 string?

如果这是真的,那么为什么同样的逻辑不适用于ICloneable.Clone(),它声明为返回object?

这个逻辑肯定适用于每个返回引用类型的接口方法吗?这种方法的任何实现(例如,ICustomFormatter.Format())理论上可以返回null - 因此返回值应该可以为空。但他们不是。


阅读了 DavidG 提供的链接,我相信该主题的讨论回答了我满意的问题:

https://github.com/dotnet/coreclr/pull/23466

【问题讨论】:

  • “在什么情况下从 object.ToString() 的实现中返回 null 是正确的?” 从不,但你可以这样做。跨度>
  • 我不认为有可接受的情况,但因为“字符串”是可以为空的,任何人都可以为他的对象编写自己的 ToString 实现......它仍然有可能......
  • The notes 部分字面上告诉你不要返回 null。我不知道为什么它被声明为string?
  • 有人讨论过这个here

标签: c# nullable-reference-types


【解决方案1】:

我看不出有人希望 anything.ToString() 永远返回 null 的原因,但谁知道呢?

然后,我认为出于兼容性原因,object.ToString() 被定义为返回 string?:这从 .NET 的 v1 开始存在,并且始终被定义为返回 stringstring 作为引用类型可以是空值。 'modern' 声明简单地指出:返回的字符串有可能为空。

请记住,这个 string? 是最新的,只是元数据:即使键入 string(就像在旧版本中一样),实现仍然可以设法返回 null。

换句话说,全新的 API 可以(并且应该)根据需要使用 Nullable 注释,但是现有库的重新键入必须尊重图书馆做到了。

我说 re-typing 因为它不是真正的打字,只是指示预期行为的注释。这有点类似于 Typescript “注释” Javascript 代码的方式:底层类型系统仍然是旧的。

【讨论】:

  • 那么按照这个逻辑,为什么ICloneable.Clone() 不被定义为public object? Clone();?不是——它被定义为public object Clone();
  • @MatthewWatson:我不是微软员工,所以我只能猜测,但我的猜测如下:contract for IClonable.Clone()一直是“创建一个新对象,它是当前实例的副本。”,这意味着返回值是非空的,因为新对象从不空(即使没有编译器支持在C# 1.0 的日子)。 object.ToString() 的契约只是声明“返回一个代表当前对象的字符串。”,这不那么严格。
  • @Heinzi 好吧 null 不是字符串(null 不是任何类型),所以我认为“返回字符串”意味着它不应该返回 null。如果您查看所有.Net 版本的object.ToString() 的文档,它会声明Your ToString() override should not return Empty or a null string.
  • @MatthewWatson:我明白你的意思。我现在可以争辩说“应该”只是一个建议(并且“空字符串”这个短语意味着 null 确实被认为是字符串的有效值),但我想这会让人毛骨悚然,而真正的原因可能是实用主义:object.ToString() 返回 null 的已知案例很多,而 ICloneable.Clone() 返回 null 的已知案例很少(如果有的话)。
  • 正如github.com/dotnet/coreclr/pull/23466 中的讨论所表明的那样,这些问题也在微软内部进行了辩论,建议将ToString 实现为返回非空字符串这一点确实是由亲调用的string?。我想这些案例是逐案讨论的,以平衡与最佳实践的兼容性......还要注意object.ToString()返回string?不会阻止覆盖返回string(这是我在同一个GitHub问题中了解到的)。
猜你喜欢
  • 2021-08-28
  • 1970-01-01
  • 2020-02-07
  • 1970-01-01
  • 1970-01-01
  • 2012-02-24
  • 1970-01-01
  • 1970-01-01
  • 2018-05-21
相关资源
最近更新 更多