对象是否应返回null并且对象集合返回空集合?

今天出现了返回空值,空对象和空集合的主题,我们希望得到其他人的意见。 我们已经阅读了关于为对象返回null的讨论以及关于返回空集合的讨论并且同意两个主题的标记答案。 但是,在我们的例子中,我们有一个包含Foo.Item类和Foo.Items类的类,它是Foo.Item对象的集合。 如果Foo.Item返回null,Foo.Items集合是否也返回null,还是应该返回空集合?

你的抽象描述是不够的。 这(大多数情况下)不是单一答案的技术问题,而是设计问题。

如果您的类也有Foo.Widget和Foo.Widgets,则Item和Widget的答案不一定相同。

但一般来说,集合属性应该返回空集合,除非有充分的理由不这样做。 任何使用这些集合的代码仍应检查null。 官方(图书馆)的建议是双重安全。

集合是一个对象。 有时候一个空对象优于null,并且这经常出现在集合中,因此人们倾向于支持空集合。 空对象可能会导致问题,并且这些问题更常出现在其他类型(特别是值 – 语义类型)中,因此当您不特别提及空集合时,人们倾向于反对空对象。

但是,在一天结束时,空集合仍然是空对象。

值得考虑的是,使用空集合的主要原因也与有时不使用空集合的原因完全相同,即我们不希望在执行for-each之前测试null。

好的,到目前为止一直很好,我们一直返回一个空集合,并且调用它们的foreach代码变得更容易编写。

但是等一下,这里有一个缺陷。 它可能对政府有用; 通过11月份提出的新的失业救济索赔来预测,并计算当月的财政费用。 答案:零! 原因是,由于目前是十月,我们还没有从11月开始有任何新的索赔。 这里的正确答案不是空集合,它是空的。

当然,这正是人们将用于非收集空对象的同一种示例。

所以,他们每个人都有自己的位置。 中间地带也是如此; 返回一个null对象,但在某些情况下,在接收它时将它与一个空对象合并。

如果是对象,则应将其返回为null,因为这样可以快速检查是否为空。 如果是收集,您应该返回空列表。 空列表非常重要,因为代码的使用者不需要检查是否为空。 考虑到他们将使用foreach他们可能正在进行的任何处理将被跳过。 如果在UI上他们试图绘制一个表,他们将显示空表。 由于所有这些好处,空集合是可行的方法。

你可以从一个非常简单的指导方针开始:

如果可以合理地避免使用,则永远不要返回空引用。

基本上,每个空引用都是程序错误的潜在邀请。 所需要的只是检查null。 通过不返回null,您几乎可以确保调用者的生活更简单。

这个简单规则的后果是:

  • 如果返回类型是某种集合类型 ,则返回空集合。

  • 如果返回类型是某些标量类型 ,则可能必须返回空引用。 一些可能的选择是:

    1. 返回特定返回类型的“零”,“空”或“默认”对象。 (按照例如EventArgs.Empty思考。)

    2. 您可以定义类似于Nullablegenerics类型的东西,它适用于值类型以及引用类型。 (理由:必须通过显式属性访问实际返回值.Value可能会使调用者更明显,他可能应首先检查.HasValue 。对于普通的,非包装的标量类型,不特别鼓励或提醒在使用该值之前检查空引用。) – (根据Maybe<'a>Option<'a>类型以及函数语言中的模式匹配来思考。)

    3. 如果空引用将指示错误,则抛出exception。

显然,这些建议中的每一个都有其自身的优点和缺点。 例如,您可能不再需要检查空值,但仍有一些情况需要检查集合是否为空; 或是否抛出exception; 等等

所以,我并不是说避免空引用本身并不会总是让你的生活变得更容易 – 但我相信指南仍然非常有用,因为它会让你思考空的反思,关于替代方案,以及它们是否会更合适。