为什么在复制时我的 Collection<T> 与 List<T> class 的工作方式不同?

Why is my Collection<T> working differently to my List<T> class when copying?

我想复制一个集合并添加新元素到其中一个(不是两个)。

在下面的代码示例中,我通过创建一个 new 并将其传递给构造函数来复制集合。之后,我只在其中一个集合中添加了一个元素。之后两个集合都包含新元素...

var listOne = new Collection<Test>();

listOne.Add(new Test());
listOne.Add(new Test());

var listTwo = new Collection<Test>(listOne);

listOne.Add(new Test());

Console.WriteLine(listOne.Count); // 3
Console.WriteLine(listTwo.Count); // 3 (NOT OK)

当我使用列表而不是集合时,它按预期工作。

var listOne = new List<Test>();

listOne.Add(new Test());
listOne.Add(new Test());

var listTwo = new List<Test>(listOne);

listOne.Add(new Test());

Console.WriteLine(listOne.Count); // 3
Console.WriteLine(listTwo.Count); // 2 (OK)

在这两种情况下,我都希望第二个列表只包含 2 个元素。为什么 Collection 和 List 有区别?

当您查看 source code 时,您会发现集合不会复制给定集合的内容。它只是引用给定的集合作为它自己的项目。

list's constructor 将给定集合的项目添加到它自己的项目存储中。

因为 Collection<T>List<T> 在它们的构造函数中做不同的事情

Collection constructor

Initializes a new instance of the Collection class as a wrapper for the specified list.

List constructor

Initializes a new instance of the List class that contains elements copied from the specified collection [...]

Collection的构造函数很简单:

public Collection(IList<T> list)
{
  if (list == null)
    ThrowHelper.ThrowArgumentNullException(ExceptionArgument.list);
  this.items = list;
}

List 构造函数比较复杂,像这样:

public List(IEnumerable<T> collection)
{
  if (collection == null)
    ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection);
  if (count == 0)
  {
    this._items = List<T>._emptyArray;
  }
  else
  {
    this._items = List<T>._emptyArray;
    foreach (T obj in collection)
      this.Add(obj);
    this._size = count;
  }
}

这是因为 Collection 是作为简单灵活的 class 创建的。出于这个原因,它有虚拟方法而不是 List.