关于c#:返回null或空集合会更好吗?

Is it better to return null or an empty collection?

假设我有一个返回数组、列表或其他集合的方法。如果内部出了问题,或者根本没有要返回的数据,那么返回空值或返回长度(count)等于0的数组(list等)更好?

事实上,这很重要,还是仅仅是开发人员的偏好问题?


最好返回空集合。当有人这样调用函数时:

1
2
3
4
foreach(var i in items)
{

}

它不会对它们抛出空引用异常。

从技术上讲,你可以说"空"与"EDOCX1"(0)的意思,但实际上,很多人(有时包括我自己)都会忘记防御性,在使用对象之前不检查它是否为空。它正在影响到其他人认为会发生的事情,这意味着更少的错误和更少的愤怒用户。


如果返回空集合而不是空集合,则迭代代码会容易得多。

但是,区分空集合和不收集数据可能很重要,因此这取决于实际类型的语义。


如果"出了问题",你应该抛出一个异常。如果没有要返回的数据,则返回空集合。开发人员通常不应该对NullReferenceException感到惊讶,当他们要求一个项目列表时,恰好没有一个项目可以返回。


这是乔希·布洛赫的一篇文章,也解释了这一点。它是用Java语言编写的,但它同样适用于C语言。返回零长度数组,而不是空值


如果出了什么问题,你不应该退回任何东西,而是抛出一个异常。

您需要就项目的空值和的含义达成一致的方法,并坚持下去。如果你是每个人都需要知道要检查的话,你要么使用空值,要么不使用空值。

我喜欢认为空-不试图或看是否有什么,可能有一些,但谁知道。

空集合-试图填充,就系统而言,没有任何项,这是一个很强的语句。

例如钱包、纸币收藏。

  • 空的-我还没打开钱包,所以我不知道里面有没有便条。
  • list=-我已经检查过了,我肯定没有任何记录,因为我把它都花在了啤酒上。

这确实是开发人员的偏好。

返回空列表

通常我会返回一个空列表,这样方法的返回对象的接收者就不需要检查是否为空,并避免任何可能的NullReferenceException

因此,任何期望列表的人都可以遍历列表,即使列表是空的(这对于每个循环都是非常快的)。

返回空值

如果您所处的环境内存不足是一个大问题,那么您可以进行优化以返回空值。然而,这意味着每个使用相关方法的人总是需要检查是否为空,并且不能解决可能的内存泄漏问题。


空和空有两种不同的含义。空集合实际上意味着"这里没有任何内容",并且可能是有效的。你怎么知道在一个空集合的基础上发生了什么错误?

虽然调用方法更安全,但这并不比返回空值更好。良好实践表明,在对对象执行操作之前,应该检查是否为空。无论如何,它是便宜的。

如果真的出了问题,你为什么不能破例呢?


我可以看到这两种情况。最终,一个数组或集合具有更大的占用空间,但从某种意义上说是"更安全的",即如果在将来的foreach/迭代中使用结果,则结果将跳过代码块,而不是以空对象异常结束。


尽管我会说这主要是开发人员的偏好问题,但返回空集合可能是更好的方法。

假设您有一个包含集合成员的对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Customer {
    private IList<Order> _orders;

    public Customer() {
        _orders = new List<Order>();
    }

    public IList<Order> Orders {
        get {
            return _orders;
        }
    }
}

通常情况下,人们更喜欢将此成员作为只读属性,以便其客户的订单在没有任何明显原因的情况下不会丢失。因此,返回null不是一种选择。使用空集合可能比使用空引用更好。因此,在类构造函数中实例化集合是一种更好的方法。

最重要的是,例如,在使用数据绑定时,返回空集合引用时可能会出现奇怪的行为,因为它最好使用空集合。

另一个示例,在迭代集合时,例如:

1
2
3
foreach (Order o in c.Orders) {
    // Do something here...
}

当集合为空时,如果不首先检查它是否为空引用,则不会执行此foreach循环。它简化了代码并最小化了其复杂性。

这取决于你所处的场景。