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