复制二维列表数组

3

我有一个列表List<MyClass>[,] myarraylist;,它已经被填充了。

我想将其复制到List<MyClass>[,] mycopy,然后更改mycopy而不更改myarraylist

最快的方法是什么?


你想一并复制所有的列表实例吗?那它们的内容呢?它们是由什么类型的列表组成的?List<什么>[,] - Blorgbeard
好的,有了格式化,我可以看到它是<MyClass>。那么,你希望mycopy拥有所有MyClass实例的副本吗? - Blorgbeard
我想要一个完全复制的myarraylist,这样我就可以更改其中一个而不影响另一个。它们是MyClass的数组,包含大约10个不同变量的字符串和整数。 - kgsw
1
@JimMischel 是的,我知道。没有代码格式化,<MyClass> 被剥离了,因为它看起来像 HTML,所以我只能看到 "List[,] mycopy"。 - Blorgbeard
我能想到的简单方法是,只需使用与“myArrayList”相同的矩阵规格初始化一个新变量,然后使用两个“for”语句来迭代遍历“rectangular array”,并复制前一个列表中相同位置的“List<MyClass>”。如果这样说得通的话。在你尝试过之前,我不想发布答案。 - Gabe
显示剩余2条评论
3个回答

3

这取决于您真正想做什么。您可以轻松地克隆数组:

List<MyClass> mcopy = new List<MyClass>[marraylist.GetUpperBound(0)+1,marraylist.GetUpperBound(1)+1];
for (int i = 0; i < marraylist.GetUpperBound(0); ++i)
{
    for (int j = 0; j < marraylist.GetUpperBound(1); ++j)
    {
        mcopy[i,j] = marraylist[i,j];
    }
}

现在,这会给你一个数组的副本。但是,mcopy[1,2]引用的是与marraylist[1,2]相同的列表。如果你修改了那个列表,也就是说,如果你写:

mcopy[1,2].Add(new MyClass(...));

那么这也会修改对应于 marraylist[1,2] 的列表。

如果你想创建列表的副本,那么你循环中的代码应该是:

mcopy[i,j] = new List<MyClass>(marraylist[i,j]);

这会创建一个新的列表,所以如果你修改了 mcopy[1,2] 中的列表,你不会修改原始数组中的列表。

但这也可能不是你想要的。因为虽然 mcopy[1,2] 包含与 marraylist[1,2] 不同的列表,但列表具有相同的内容。所以如果你写了 mcopy[1,2][1].SomeProperty = 42;,那么你也会修改 marraylist[1,2][1] 中对象的内容,因为它们是同一个对象。

如果你想要列表和对象的副本,那么你的内部循环代码变成:

mcopy[i,j] = marraylist[i,j].Select(m => new MyClass(/* create from m */)).ToList();
/* create from m */ 注释的意思是你可以通过以下方式来进行深层次复制 m。一种方式是传递给复制构造函数(如果有),另一种方式是传递单个参数,或者如果类中有克隆方法,则使用该方法。你需要以某种方式对MyClass实例进行深层次复制。
是的,这很复杂。这里的“copy”一词相当多义,你如何操作完全取决于你所使用的“复制”的定义。你想要复制数组(只需复制引用)还是数组的内容(创建具有相同对象的新列表),还是列表的内容(创建带有相同数据的新对象的新列表)?

很好解释的答案 - 在原帖中也基本上评论了同样的事情 - 我只是想看看他在发帖之前是否会尝试。不过还是要给这个深入的回答点赞。 - Gabe

0
如果MyClass有一个拷贝构造函数:
var newList = new List<MyClass>[oldList.GetLength(0), oldList.GetLength(1)];

for (int i = 0; i < oldList.GetLength(0); i++)
    for (int j = 0; j < oldList.GetLength(1); j++)
        newList[i, j] = oldList[i, j].Select(x => new MyClass(x)).ToList();

如果它没有拷贝构造函数,并且你无法添加一个,那么你就需要自己编写一个函数来复制MyClass的内容。
newList[i, j] = oldList[i, j].Select(x => CloneMyClass(x)).ToList();

这不是一个MyClass实例的二维数组,而是一个List<MyClass>的二维数组。 - Jim Mischel
是的,它是一个二维数组,元素类型为List<MyClass>,所以[0,0]位置可能有10个元素,而[0,1]位置可能有2个元素。 - kgsw
糟糕,没有仔细阅读问题。我已更新答案。 - smead

0
这可能有效。这是一个针对2D IEnumerables的扩展方法。这意味着它可以与任何实现了IEnumerable接口的东西一起使用,只要你的类T实现了ICloneable接口。
public static IEnumerable<IEnumerable<T>> Clone<T>(this IEnumerable<IEnumerable<T>> twoDList) where T : ICloneable
        {
            if (twoDList != null)
            {
                List<List<T>> result = new List<List<T>>();
                for (int i = 0; i < twoDList.Count(); i++)
                {
                    List<T> aList = new List<T>();
                    for (int j = 0; j < twoDList.ElementAt(i).Count(); j++)
                    {
                        aList.Add(twoDList.ElementAt(i).ElementAt(j));
                    }
                    result.Add(aList);
                }
                return result;
            }
            else
            {
                return null;
            }
        }

它还应该适用于实现IEnumerable的不规则2D结构。 以下是示例用法:
List<List<MyClass>> cloned = original2DStructure.Clone();

关于如何使你的类实现 ICloneable 的帮助可以在这里找到。


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