为什么通用列表AddRange返回void而不是列表?

时间:2012-09-14 21:30:24

标签: c#

namespace System.Collections.Generic
  public List<T>    
    public void AddRange(IEnumerable<T> collection)

似乎可能是故意的设计决定不返回某些东西。我对此感到厌烦,期待AddRange“流利”。

我很好奇是否有人知道设计动机,如果有的话,什么也不回来?

3 个答案:

答案 0 :(得分:22)

在LINQ出局之前,在.NET 2.0中添加了AddRange方法,而且“流畅性”真的根本不流行。当时,没有人期望AddRange返回任何东西。另外,在那个版本的.NET中,没有List对象的初始化器,因此你 将Add()一大串项添加到列表中。 AddRange提供了一个快捷方式,可以不必循环遍历并逐个添加对象。

等效的LINQ方法是IEnumerable<T>.Concat()

答案 1 :(得分:3)

其他答案(基本上)是正确的,但它们都没有解决为什么 AddRange可能会返回某些内容的可能性。

这样做的一个原因是创建一个流畅的API,如下所示:

list.Add(1).Add(2).Add(3);
list.AddRange(aGroupOfNumbers).AddRange(theNextGroupOfNumbers);

为了实现这一点,列表只是在改变列表的方法的末尾返回自己。正如Trisped所说,StringBuilder在引入通用List<T>之前就已经这样做了。

如Felix K所暗示的那样,返回某些东西的另一个原因是该类型是不可变的。如果列表是不可变的,那么不能在方法结束时返回它自己,因为它不能自我变异;并且它不能再返回void,因为它不能自我变异。为了反映方法契约定义的更改,列表必须创建一个包含更改的新实例,然后,当然,它必须将该新实例返回给调用者。在涉及集合时,人们有时很难想到这一点,但有一种非常着名的行为方式:System.String。正如d-b所说,没有人希望列表返回任何内容,因为“经典”命令式编程风格在改变数据结构时使用void方法。

System.Collections.Generic命名空间的设计者可能没想过给他们的类型提供流畅的API,但是如果他们这样做了,我可以看到他们可能已经决定如何反对它。当然,StringBuilder中流畅的API的情况比List<T>中流畅的API的情况要强一些。

答案 2 :(得分:1)

AddRange方法将collection添加到调用该函数的List<T>实例。

因此,您不需要返回任何内容,因为结果已经存在。

当要完成的工作没有创建新对象时,则不返回任何内容。我想到的唯一例外是StringBuilder类,其中大多数成员方法返回指向调用实例的指针。这是为了启用命令链,并在文档中特别提到。