2013-03-07 118 views
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」而不是「收藏」。我怎樣才能做到這一點?是不是下面一行做深拷貝:

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

如果是這樣,那麼爲什麼原始對象會受到影響?

我知道我可以通過這條線實現我的目標太:

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

但我在有關Remove東西和深拷貝的東西上面發生的困境。

+0

這是System.Collections.ObjectModel.Collection – 2013-03-07 07:32:31

回答

3

這是因爲Collection<T>(IList<T>) constructor的行爲:

列表中的元素不會被複制。該列表由集合包裝,以便後續對列表元素的更改通過集合可見。

如果你想收集的淺拷貝,你可以使用List<T>代替:

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

(這是一個有點古怪,看慣Collection<T>這樣在所有它通常用作。所述類其它通用集合。)


這是一個淺拷貝,因爲它只是複製每個元素的值作爲參考,而不是克隆每個Foo對象。如果你寫道:

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

...它仍然會打印「你好!」。在現有集合周圍創建封裝並不是真正創建副本,淺深。

+0

你的意思是通過這個「新列表(集合)」進行深層複製;對吧?而不是我假設的淺拷貝在您的回覆中是一個錯字。 – 2013-03-07 07:34:32

+0

@RockySingh:不,我的意思是淺拷貝。深拷貝將克隆每個元素。淺拷貝只是複製*引用* - 但仍然創建一個獨立的集合。我編輯了我的答案以提供腳註。 – 2013-03-07 07:35:46

1

您需要克隆它,newCollection只是對原始集合的引用。

+0

那麼這一行然後「var newCollection = new Collection (collection);」 – 2013-03-07 07:31:08

+0

@RockySingh:查看我的答案 - 和文檔。 – 2013-03-07 07:32:18

+0

你正在傳遞構造函數裏原來的'collection'對象.. – animaonline 2013-03-07 07:33:11

0

Collection<Foo>(collection)僅包裝提供的集合,以便集合的任何更改也會影響原始集合。

您應該使用List<Foo>來做你想做的事情,導致構造函數List<T>(IEnumerable<T>)從原始集合中複製這些值。

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

您可以嘗試這樣做。

var newCollection = new Collection<Foo>(); 

collection.ToList().ForEach(x => newCollection.Add(x));