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

似乎不返回某些东西可能是一个有意的设计决定。我被这个期望 AddRange 是“流利的”咬了。

我只是好奇是否有人知道设计动机,如果有的话,什么都不返回?

4

4 回答 4

29

AddRange方法是在 .NET 2.0 中添加的,在 LINQ 出现之前,当时“流畅性”根本不流行。当时,没有人期望AddRange返回任何东西。另外,在那个版本的 .NET 中,没有 List 对象的初始化程序,所以你必须Add() 一堆项目到列表中。AddRange 提供了一种快捷方式,无需逐个循环和添加对象。

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

于 2012-09-14T21:33:35.770 回答
3

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

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

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

为了实现这一点,列表只是在改变列表的方法的末尾返回自身。正如 Trisped 所指出的,在引入StringBuilder泛型之前就这样做List<T>了。

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

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

于 2012-09-14T22:24:15.073 回答
2

该列表不是结构,因此它会发生变异,如果您想要一个避免变异的列表,您必须编写自己的列表或使用 Linq 或只使用以下代码:

List<T> newList = new List<T>(originalList);
newList.AddRange(...);

或者在构造列表时(IEnumerable<T>.Concat()在构造函数处)使用 Linq。有很多方法可以避免突变。

于 2012-09-14T21:37:01.050 回答
1

AddRange方法添加collectionList<T>调用该函数的实例。

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

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

于 2012-09-14T21:37:14.990 回答