不使用原始引用创建 List<t> 的副本

3

我知道这个问题以前已经被讨论过,但从我在文章中的理解来看,这应该是可行的。

示例代码:

我有一个自定义类型:

public class MyType
{
    public List<MySubType> Movie { get; set; }
    public List<int> Ranks { get; set; }
    public string Location { get; set; }
    public string Released { get; set; }
}

我随后创建了一个这种类型的列表。
List<MyType> myMovies = new List<MyType>();

在代码的后面,我需要创建这个列表的副本并对其进行更改,而不会影响原始列表。

List<MyType> copyMovies = new List<MyType>(myMovies);

但是现在,如果我从copyMovies列表中删除
copyMovies.Movie.RemoveAt(x);

它从两个列表中都移除

除非我完全错过了什么,这篇文章表明我应该能够更改副本列表而不影响原始列表。


8
不是真的。如果你从第二个中删除,那么它不会从第一个中被删除。 - Tim Schmelter
6
你的代码应该能够运行。new List<MyType>(myMovies) 应该创建一个包含相同元素的新列表。你的问题似乎与这个问题无关。 - Avish
1
你确定了吗?你真的测试过RemoveAt函数了吗? - Only a Curious Mind
1
如果是这样,我相信在某个阶段你会执行这个操作 copyMovies = myMovies; - Sriram Sakthivel
1
@Fred 我已经测试了你的实现,一切都正常。请再次执行你的测试。 - Only a Curious Mind
显示剩余15条评论
3个回答

17
您可以直接在原始列表上调用ToList(),它会生成一个副本。

3
我很确定你的代码应该可以工作。 MSDN 关于构造函数的说明是:

初始化一个新的 List 类的实例,包含从指定集合复制的元素并且具有足够的容量来容纳复制的元素数量。

你确定你没有漏掉什么吗? 编辑: 你确实漏掉了一些东西... 你的示例是错误和误导性的。 你的编辑表明你尝试从列表中删除一个项目,在复制父类时,这些项目不会被复制/克隆。 您需要克隆您的类的每个属性。 参考 深度克隆对象

是的,我确实错过了一些事情,并为明显造成的困扰向SO社区表示无保留的道歉。感谢您提供的链接。 - Fred
@Fred:没问题。通常人们都知道他们正在谈论什么,所以不要一直说它不起作用并且你已经测试过了,而实际上它并没有。但最终,我们都曾有过这样的经历。 - Patrick Hofman

2

如果你认为使用 copyMovies.RemoveAt(x) 而不是 copyMovies.Movie.RemoveAt(x) 只是稍微有点误导人,那么抱歉,我的朋友,你只是在浪费我们的时间。

内部列表已经被引用复制,所以你需要复制整个内部列表,例如:

List<MyType> copyMovies = new List<MyType>(myMovies.Select (m => new MyType()
{
    Movie = new List<MySubType>(m.Movie),
    Ranks = m.Ranks,
    Location = m.Location,
    Released = m.Released
}));

或者
List<MyType> copyMovies = myMovies.Select (m => new MyType()
{
    Movie = new List<MySubType>(m.Movie),
    Ranks = m.Ranks,
    Location = m.Location,
    Released = m.Released
}).ToList();

或者使用复制构造函数:

//in MyType definition
public MyType(MyType objectToCopy)
{
    Movie = new List<MySubType>(m.Movie);
    Ranks = m.Ranks;
    Location = m.Location;
    Released = m.Released;
}

然后你就可以这样使用它:
List<MyType> copyMovies = myMovies.Select (m => new MyType(m));

我连续工作了28个小时,错过了一些细节,即使现在我理解了问题所在,仍然不明白为什么克隆对象只会克隆其中的一部分。为什么不开枪打死我呢! - Fred
1
@Fred:这被称为“设计如此”。当克隆具有多个、甚至是循环引用的对象时,你认为会发生什么?如何确定要克隆什么,不克隆什么呢? - Patrick Hofman
@Fred 不,整个列表已经被克隆了。你需要意识到这个列表不持有引用类型对象,它只持有对它们的引用。所有引用都已经被正确地克隆了,它们只是指向相同的 MyType 对象。 - Tarec

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接