当前位置: 动力学知识库 > 问答 > 编程问答 >

c# - Modify new collection without touching the original one

问题描述:

My goal is to get a copy of collection with specified item removed from it without touching the items of original collection. I have the following class:

public class Foo

{

public string Name { get; set; }

}

and the operation I am doing is:

 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);

}

i.e I am removing the item from "newCollection" but the issue is that the following line:

newCollection.Remove(f);

is removing the item from original collection too i.e from "collection" object. I want to modify "newCollection" only and not "collection". How can I do that? Isn't the following line doing a deep copy:

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

if so, then why the original object is affected?

I know I can achieve my goal via this line too:

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

but I am in dilemma about the Remove stuff and deep copy stuff happening above.

网友答案:

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.

网友答案:

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

网友答案:

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);
    }
网友答案:

You could try doing this instead.

  var newCollection = new Collection<Foo>();

collection.ToList().ForEach(x => newCollection.Add(x));
分享给朋友:
您可能感兴趣的文章:
随机阅读: