我想要克隆一个List你只需要调用:
ListcloneList = new List (originalList);
但是我在我的代码中尝试了这一点,我似乎得到的效果暗示上面只是在做:
cloneList = originalList ...因为对cloneList的更改似乎正在影响originalList.
那么克隆List的方法是什么?
编辑:
我在考虑做这样的事情:
public static ListClone (this List originalList) where T : ICloneable { return originalList.ConvertAll(x => (T) x.Clone()); }
EDIT2:
我拿了Binoj Antony建议的深拷贝代码并创建了这个扩展方法:
public static T DeepCopy(this T original) where T : class { using (MemoryStream memoryStream = new MemoryStream()) { BinaryFormatter binaryFormatter = new BinaryFormatter(); binaryFormatter.Serialize(memoryStream, original); memoryStream.Seek(0, SeekOrigin.Begin); return (T)binaryFormatter.Deserialize(memoryStream); } }
EDIT3:
现在,假设列表中的项目是结构.如果我打电话会怎么样?:
ListcloneList = new List (originalList);
我非常肯定,我会得到一个填充了新的独特项目的列表,对吗?
这会工作......
ListcloneList = new List (originalList);
当你说"因为对cloneList的更改似乎正在影响originalList".- 您的意思是更改列表,还是更改项目 ......
添加/删除/交换项目正在更改列表 - 因此,如果我们这样做:
cloneList.Add(anotherItem);
你会发现它cloneList
比...更长originalList
.但是,如果内容是引用类型(类),那么两个列表仍然指向相同的底层对象 - 所以如果我们这样做:
cloneList[0].SomeObjectProperty = 12345;
然后这也将显示originalList[0].SomeObjectProperty
- 只有一个对象(两个列表之间共享).
如果这是问题,你将不得不克隆列表中的对象 - 然后你进入整个深层和浅层问题......这是问题吗?
对于浅拷贝,你也许能够使用的东西非常喜欢的答案在这里 -简单地用TTo = TFrom
(也许简化为一个单一的T
).
您可以使用以下代码制作列表的深层副本或支持序列化的任何其他对象:
此外,您可以将此用于v 2.0及更高版本的任何.NET框架版本,并且可以应用类似技术(删除泛型的使用)并在1.1中使用
public static class GenericCopier{ public static T DeepCopy(object objectToCopy) { using (MemoryStream memoryStream = new MemoryStream()) { BinaryFormatter binaryFormatter = new BinaryFormatter(); binaryFormatter.Serialize(memoryStream, objectToCopy); memoryStream.Seek(0, SeekOrigin.Begin); return (T) binaryFormatter.Deserialize(memoryStream); } } }
你可以用它来调用它
ListdeepCopiedList = GenericCopier >.DeepCopy(originalList);
测试是否有效的完整代码:
static void Main(string[] args) { ListoriginalList = new List (5); Random random = new Random(); for(int i = 0; i < 5; i++) { originalList.Add(random.Next(1, 100)); Console.WriteLine("List[{0}] = {1}", i, originalList[i]); } List deepCopiedList = GenericCopier >.DeepCopy(originalList); for (int i = 0; i < 5; i++) Console.WriteLine("deepCopiedList[{0}] value is {1}", i, deepCopiedList[i]); }
我怀疑你的实际例子会有问题,因为它int
是一个值类型.例如:
using System; using System.Collections.Generic; class Test { static void Main() { ListoriginalList = new List { 5, 6, 7 }; List cloneList = new List (originalList); cloneList.Add(8); cloneList[0] = 2; Console.WriteLine(originalList.Count); // Still 3 Console.WriteLine(originalList[0]); // Still 5 } }
但是,正如Marc所说,如果您的列表包含可变引用类型,则克隆列表将只采用浅表副本 - 如果您改变列表引用的对象,则这些更改将通过两个列表可见.替换一个列表中的元素不会更改另一个列表中的等效元素:
using System; using System.Collections.Generic; class Dummy { public int Value { get; set; } public Dummy (int value) { this.Value = value; } } class Test { static void Main() { ListoriginalList = new List { new Dummy(5), new Dummy(6), new Dummy(7) }; List cloneList = new List (originalList); cloneList[0].Value = 1; cloneList[1] = new Dummy(2); Console.WriteLine(originalList[0].Value); // Changed to 1 Console.WriteLine(originalList[1].Value); // Still 6 } }
要对元素类型实现的列表进行"深度克隆" ICloneable
,请使用:
ListcloneList = originalList.ConvertAll(x => (Foo) x.Clone());
但是,这个克隆的真正深度将取决于ICloneable
元素类型的实现- ICloneable
通常被认为是一件坏事,因为它的合同是如此模糊.