用于创建集合中所有元素的深层副本的通用方法

我有各种不同对象类型的ObservableCollections。 我想编写一个方法来获取任何这些对象类型的集合,并返回一个新集合,其中每个元素都是给定集合中元素的深层副本。 以下是特定类的示例

private static ObservableCollection DeepCopy(ObservableCollection list) { ObservableCollection newList = new ObservableCollection(); foreach (PropertyValueRow rec in list) { newList.Add((PropertyValueRow)rec.Clone()); } return newList; } 

如何为任何实现ICloneable的类使这个方法通用?

你可以这样做:

 private static ObservableCollection DeepCopy(ObservableCollection list) where T : ICloneable { ObservableCollection newList = new ObservableCollection(); foreach (T rec in list) { newList.Add((T)rec.Clone()); } return newList; } 

请注意,通过使用IEnumerable可以使这更通用,而LINQ使它更容易:

 private static ObservableCollection DeepCopy(IEnumerable list) where T : ICloneable { return new ObservableCollection(list.Select(x => x.Clone()).Cast()); } 
 private static ObservableCollection DeepCopy(ObservableCollection list) where T : ICloneable { ObservableCollection newList = new ObservableCollection(); foreach (T rec in list) { newList.Add((T)rec.Clone()); } return newList; } 

我使用了一个非常相似的函数,它可以构造所有可以构造的ICollections(例如许多标准集合):

  public static TContainer CloneDeep( TContainer r ) where T : ICloneable where TContainer: ICollection, new() { // could use linq here, but this is my original pedestrian code ;-) TContainer l = new TContainer(); foreach(var t in r) { l.Add( (T)t.Clone() ); } return l; } 

遗憾的是,编译器无法推断出类型,因此必须明确地传递它们。 对于一些以上的电话,我写了一个专业化。 这是Lists的一个例子(它本身可以通过隐式推导的T来调用)。

  public static List CloneListDeep( List r ) where T : ICloneable { return CloneDeep, T>( r ); } 

我广泛使用此函数,以便创建列表的副本,作为可以取消的对话框上的datagridviews的数据源。 取消对话框时,简单地丢弃修改后的列表; 当对话框确定时,编辑的列表只是替换原始列表。 当然,这种模式的先决条件是具有语义正确且维护良好的T.clone()