集合请求将有零个项目时的预期行为


13

假设您得到以下信息...

List<Thing> theThings = fubar.Things.All();

如果没有什么可以返回的,您期望fubar.Things.All()返回什么?

编辑:感谢您的意见。我会稍等一下,并接受最多的评论。

我同意到目前为止的回应,尤其是那些建议收藏空的回应。供应商为API提供了多次调用,类似于上面的示例。去年,通过其API实现收入460万美元的供应商BTW。他们做了我根本不同意的事情-他们抛出了异常。


似乎是一个非常坚实的共识[here] [1]:空集合。总是。[1]:stackoverflow.com/questions/1969993/...
杰西C.切片机

数据类型是Things什么?如果让该Things字段返回null是有意义的,那么对您来说,接收异常是有意义的,因为在调用之前您没有检查null All()。但是,我同意那些认为fubar.Things应该返回空集合而不是null的人的观点。
科林D

我明白你在做什么,科林。在这种情况下,您可以假定事物存在并且All()是静态的。该异常特定于集合为空,而不是其他原因。
abscode 2012年

天哪,他们抛出异常...!o_O
Stuart标志着

现在,更有趣的问题是,在这种一般情况下,任何人都可能不得不抛出什么原因,或者是什么使得这种情况如此特殊以致可以抛出??!
马丁·巴

Answers:


29

在这两种可能性中(即返回a null或返回一个空集合),我会选择返回一个空集合,因为它使调用者可以跳过对返回值的检查。而不是写这个

List<Thing> theThings = fubar.Things.All();
if (theThings != null) {
    for (Thing t : theThings) {
        t.doSomething();
    }
}

他们将能够编写以下代码:

List<Thing> theThings = fubar.Things.All();
for (Thing t : theThings) {
    t.doSomething();
}

第二个代码段更短并且更易于阅读,因为嵌套级别降低了一个。


2
我想我也会发现从概念上更容易理解,因为“集合为空”(无项目)。Null是“没有集合”,这是完全不同的。(这还应涵盖逻辑上不可能的内容-奇数的所有项目的集合,偶数也应为空,而不是null)。老实说,我不确定是什么(逻辑上)会构成一个空集……(即使您裸露在一个岛上,您的财产也是一个空集,而不是一个空集)
Clockwork-Muse

@ X-Zero但是,如果您赤身裸体,那么“拥有背包中的财产”可能会返回空集,因为您甚至根本没有背包。它可能是BackpackNotFoundException,但只有在确实无法预料的情况下才可以。例如,在岛屿生存游戏中,它应该是正常状态。
Izkata 2012年

额外的null检查是什么有助于我晚上入睡。
Joel B

6

我希望有一个空的清单。theThings仍然是一个对象,但theThings.Count还是theThings.size()会回来0


5

空对象模式解决了类似的设计问题

...而不是使用空引用来传达对象的缺失(例如,不存在的客户),而是使用了一个对象,该对象实现了预期的接口,但其方法主体为空。这种方法优于有效的默认实现的优点是,Null对象非常容易预测,并且没有副作用:它什么都不做。

例如,一个函数可以检索目录中的文件列表,并对每个文件执行一些操作。在目录为空的情况下,一种响应可能是引发异常或返回空引用而不是列表。因此,期望列表的代码必须在继续之前验证它实际上是否已经存在一个列表,这会使设计变得复杂...

特别适用于您的情况的建议(List不存在Things 时返回)是:

...通过返回一个空对象(即一个空列表),无需验证返回值实际上是一个列表。调用函数可以像平常一样简单地迭代列表,实际上什么也没做。但是,仍然可以检查返回值是否为空对象(例如,空列表),并根据需要做出不同的反应。


3

恕我直言,您应该返回一个EMPTY值。我不了解C#,但是在Java中,我们有以下内容:

  List list = Collections.EMPTY_LIST;
  Set set = Collections.EMPTY_SET;
  Map map = Collections.EMPTY_MAP;

  // For the type-safe 
  List<String> s = Collections.emptyList();
  Set<Long> l = Collections.emptySet();
  Map<Date> d = Collections.emptyMap();

http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Collections.html


1
的C#当量Enumerable.Empty<T>(),它返回一个空的IEnumerable<T>(见msdn.microsoft.com/en-us/library/bb341042.aspx
阿夫纳沙哈尔-卡什坦

1
当前文档在这里:docs.oracle.com/javase/7/docs/api/java/util/Collections.html-1.4.2文档现在已有十多年的历史了。
斯图尔特(Stuart Marks)

2

我将返回一个空集合,而不是返回一个空值,因为那样可以避免在调用代码中编写空验证。


2

这两种解决方案含义不同。

如果您要退回的东西只有零,那么您始终会返回一个空集合!以目录列表为例。如果目录中没有文件,则返回空文件集合。

另一方面,如果该目录不存在,那实际上是不合适的。“我什么也退不回来”意味着完全不同。在这种情况下,您应根据情况返回null或引发异常,不要仅仅因为没有错误就返回空集合。


非常合理的解释。返回的结果不应涵盖无效状态,对此我们有例外。
Ivaylo Slavov
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.