2

我的目标是在不触及原始收藏的项目的情况下,获取一份从中删除指定项目的收藏副本。我有以下课程:

public class Foo
{
    public string Name { get; set; }
}

我正在做的操作是:

 var collection = new Collection<Foo>
                         {
                             new Foo {Name = "Name1"},
                             new Foo {Name = "Name2"},
                             new Foo {Name = "Name3"},
                             new Foo {Name = "Name4"}
                         };
    var newCollection = new Collection<Foo>(collection);

    Foo f = collection.FirstOrDefault(x => x.Name == "Name2");
    if (f != null)
    {
        newCollection.Remove(f);
    }

即我正在从“newCollection”中删除该项目,但问题是以下行:

newCollection.Remove(f);

也从原始集合中删除该项目,即从“集合”对象中。我只想修改“newCollection”而不是“collection”。我怎样才能做到这一点?以下行不是在做深拷贝:

 var newCollection = new Collection<Foo>(collection);

如果是这样,那么为什么原始对象会受到影响?

我知道我也可以通过这条线实现我的目标:

var newCollection = collection.Where(x => x.Name != "Name2");

但我对上面发生的删除东西和深拷贝的东西进退两难。

4

4 回答 4

3

This is because of the behaviour of the Collection<T>(IList<T>) constructor:

The elements of the list are not copied. The list is wrapped by the collection, so that subsequent changes to the elements of the list are visible through the Collection.

If you want a shallow copy of the collection1, you could use List<T> instead:

List<Foo> newCollection = new List<T>(collection);

(It's a little odd to see Collection<T> used like this at all. It's normally used as the base class for other generic collections.)


1 It's a shallow copy because it's just copying the value of each element as a reference, rather than cloning each Foo object. If you wrote:

newCollection[0].Name = "Hello!";
Console.WriteLine(collection[0]);

... it would still print "Hello!". Creating a wrapper around an existing collection isn't really creating a copy at all, shallow or deep.

于 2013-03-07T07:31:58.447 回答
1

You need to clone it, the newCollection is only a reference to the original collection.

于 2013-03-07T07:29:17.177 回答
0

Collection<Foo>(collection) wrapps only the provided collection, so that any changes to the collection also effect the original collection.

You should use a List<Foo> to do what you want, cause constructor of List<T>(IEnumerable<T>) copies the values from the original collection.

var collection = new Collection<Foo>
                         {
                             new Foo {Name = "Name1"},
                             new Foo {Name = "Name2"},
                             new Foo {Name = "Name3"},
                             new Foo {Name = "Name4"}
                         };
    var newCollection = new List<Foo>(collection);

    Foo f = collection.FirstOrDefault(x => x.Name == "Name2");
    if (f != null)
    {
        newCollection.Remove(f);
    }
于 2013-03-07T07:31:16.310 回答
0

You could try doing this instead.

  var newCollection = new Collection<Foo>();

collection.ToList().ForEach(x => newCollection.Add(x));
于 2013-03-07T07:31:30.670 回答