我有各种不同对象类型的ObservableCollections。我想编写一个方法来获取任何这些对象类型的集合,并返回一个新集合,其中每个元素都是给定集合中元素的深层副本。以下是特定类
的示例 private static ObservableCollection<PropertyValueRow> DeepCopy(ObservableCollection<PropertyValueRow> list)
{
ObservableCollection<PropertyValueRow> newList = new ObservableCollection<PropertyValueRow>();
foreach (PropertyValueRow rec in list)
{
newList.Add((PropertyValueRow)rec.Clone());
}
return newList;
}
如何为任何实现ICloneable的类使这个方法通用?
答案 0 :(得分:25)
你可以这样做:
private static ObservableCollection<T> DeepCopy<T>(ObservableCollection<T> list)
where T : ICloneable
{
ObservableCollection<T> newList = new ObservableCollection<T>();
foreach (T rec in list)
{
newList.Add((T)rec.Clone());
}
return newList;
}
请注意,您可以通过IEnumerable<T>
使其更加通用,而LINQ使其变得更加容易:
private static ObservableCollection<T> DeepCopy<T>(IEnumerable<T> list)
where T : ICloneable
{
return new ObservableCollection<T>(list.Select(x => x.Clone()).Cast<T>());
}
答案 1 :(得分:3)
private static ObservableCollection<T> DeepCopy<T>(ObservableCollection<T> list)
where T : ICloneable
{
ObservableCollection<T> newList = new ObservableCollection<T>();
foreach (T rec in list)
{
newList.Add((T)rec.Clone());
}
return newList;
}
答案 2 :(得分:0)
我使用了一个非常相似的函数,它适用于所有可以构造的ICollections(例如许多标准集合):
public static TContainer CloneDeep<TContainer, T>( TContainer r )
where T : ICloneable
where TContainer: ICollection<T>, 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<T> CloneListDeep<T>( List<T> r ) where T : ICloneable
{
return CloneDeep<List<T>, T>( r );
}
我广泛使用此函数,以便创建列表的副本,作为可以取消的对话框上的datagridviews的数据源。取消对话框时,简单地丢弃修改后的列表;当对话框确定时,编辑的列表只是替换原始列表。当然,这种模式的先决条件是具有语义正确且维护良好的T.clone()
。