我知道这是多次被问到的,我正在尝试实现它。我有以下列表
internal class GenList
{
public string Col1 { set; get; }
public string Col2 { set; get; }
}
List<GenList> MainList = new List<GenList>();
我想将列表复制到其他列表中,如果在主列表中更改了某些内容,则不希望内容在克隆列表中更改。所以我想在下面做
List<GenList> cloned = MainList.ConvertAll(GenList => new GenList {});
我不知道在上面的那些花括号内输入什么。
答案 0 :(得分:10)
如果在主列表中更改了某些内容,则不希望内容在克隆列表中更改。
听起来你想要一个深刻的克隆,基本上。换句话说,创建一个新列表,其中每个元素是原始列表中元素的副本,而不仅仅是对原始列表引用的同一对象的引用。
在你的情况下,这很简单:
var cloned = MainList.ConvertAll(x => new GenList { Col1 = x.Col1, Col2 = x.Col2 });
或者使用LINQ:
var cloned = MainList.Select(x => new GenList { Col1 = x.Col1, Col2 = x.Col2 })
.ToList();
但请注意:
要考虑的选项:
DeepClone()
添加GenList
方法,将逻辑保存在一个地方,但很多地方都需要它。GenList(GenList)
正确复制GenList
immutable),此时集合的浅克隆就足够了。答案 1 :(得分:2)
这是一个通过序列化的快速深度克隆解决方案:
[Serializable]
public class GenList
{
public string Col1 { set; get; }
public string Col2 { set; get; }
public GenList DeepClone()
{
using (var stream = new MemoryStream())
{
var formatter = new BinaryFormatter();
formatter.Serialize(stream, this);
stream.Position = 0; //reset stream
var cloned = formatter.Deserialize(stream) as GenList;
return cloned;
}
}
和验证测试:
[TestClass]
public class DeepCloneTests
{
[TestMethod]
public void ReferencesAreNotMaintained()
{
var object1 = new GenList() { Col1 = "a", Col2 = "b" };
var cloned = object1.DeepClone();
Assert.AreEqual(object1.Col1, cloned.Col1);
Assert.AreEqual(object1.Col2, cloned.Col2);
cloned.Col1 = "c";
cloned.Col2 = "d";
Assert.AreNotEqual(object1.Col1, cloned.Col1);
Assert.AreNotEqual(object1.Col2, cloned.Col2);
}
}