这是一个一般性的问题(但我使用c#),最好的方法(最佳实践)是什么,对于一个有集合作为返回类型的方法,你返回null集合还是空集合?


当前回答

Go似乎是首选nil而不是空数组的一种语言。

https://github.com/golang/go/wiki/CodeReviewComments#declaring-empty-slices

当声明一个空切片时,优先使用var t []string而不是t:= []string{}。前者声明一个nil切片值,而后者非nil但长度为0。它们在功能上是等价的——它们的len和cap都是0——但是nil片是首选样式。

其他回答

我喜欢在这里用适当的例子来解释。

考虑一个案例。

int totalValue = MySession.ListCustomerAccounts()
                          .FindAll(ac => ac.AccountHead.AccountHeadID 
                                         == accountHead.AccountHeadID)
                          .Sum(account => account.AccountValue);

这里考虑我使用的函数..

1. ListCustomerAccounts() // User Defined
2. FindAll()              // Pre-defined Library Function

我可以很容易地使用ListCustomerAccount和FindAll代替。

int totalValue = 0; 
List<CustomerAccounts> custAccounts = ListCustomerAccounts();
if(custAccounts !=null ){
  List<CustomerAccounts> custAccountsFiltered = 
        custAccounts.FindAll(ac => ac.AccountHead.AccountHeadID 
                                   == accountHead.AccountHeadID );
   if(custAccountsFiltered != null)
      totalValue = custAccountsFiltered.Sum(account => 
                                            account.AccountValue).ToString();
}

注意:由于AccountValue不为空,Sum()函数不会为空 返回null。因此我可以直接使用它。

框架设计指引第二版(第256页):

不返回空值从 集合属性或方法 返回集合。返回空 集合或空数组。

这是另一篇关于不返回null的好处的有趣文章(我试图在Brad Abram的博客上找到一些东西,他链接到了这篇文章)。

编辑-正如Eric Lippert现在对原始问题的评论,我也想链接到他的优秀文章。

我认为null与空集合不同,您应该选择哪一个最能代表您要返回的内容。在大多数情况下,null什么都不是(SQL除外)。空的收藏是一种东西,尽管是一种空的东西。

如果你不得不选择一个或另一个,我会说你应该倾向于一个空集合而不是null。但有时空集合与空值并不相同。

空集合。总是这样。

这糟透了:

if(myInstance.CollectionProperty != null)
{
  foreach(var item in myInstance.CollectionProperty)
    /* arrgh */
}

在返回集合或枚举对象时,NEVER返回null被认为是最佳实践。ALWAYS返回一个空的可枚举/集合。它可以防止前面提到的废话,并防止你的车被同事和你的类的用户怂恿。

在谈论属性时,总是设置一次属性,然后忘记它

public List<Foo> Foos {public get; private set;}

public Bar() { Foos = new List<Foo>(); }

在.NET 4.6.1中,你可以将这些内容进行大量压缩:

public List<Foo> Foos { get; } = new List<Foo>();

当谈论返回枚举对象的方法时,你可以很容易地返回一个空的枚举对象而不是null…

public IEnumerable<Foo> GetMyFoos()
{
  return InnerGetFoos() ?? Enumerable.Empty<Foo>();
}

使用Enumerable.Empty<T>()可以被视为比返回一个新的空集合或数组更有效。

返回null可能更有效,因为不会创建新的对象。然而,它也经常需要一个空检查(或异常处理)。

从语义上讲,null和空列表的意思是不同的。这些差异是微妙的,在特定的情况下,一种选择可能比另一种更好。

不管你的选择是什么,记录下来以避免混淆。