C#中与List<String[]>相关的“有趣”问题

10

我的C#应用程序中有一些与List有关的奇怪问题。这可能是分配错误或我的操作不正确(我是普通的C#开发人员)。 让我举个接近我的例子:

List<String[]> MyPrimaryList = new List<String[]>();
List<String[]> MySecondaryList = new List<String[]>();
String[] array;

String arrayList = "one,two,three,four,five";
array = arrayList.Split(',');

MyPrimaryList.Add(array);
MySecondaryList.Add(array);

MyPrimaryList[0][0] += "half";
所以我希望第一个数组中第一个值在MyPrimaryList中为"onehalf",而在MySecondaryList中为"one"。 但我的问题/难题是两个列表都使用"onehalf"作为它们的第一个值更新。

你有什么好的解释吗? :)

谢谢!!


1
你正在将相同的数组添加到两个列表中,因此它们都指向你正在更改的数组元素。 - Adam Houldsworth
你正在将同一个对象添加到两个列表中 - 换句话说,只有一个array,你没有在任何地方创建副本... - tpeczek
5个回答

17

String[] array;是一个引用类型。你将该对象在内存中的位置的引用添加到两个列表中,因此它们都保存着相同的数据。

如果你需要第二个列表拥有array的副本,则可以使用Array.Copy

List<String[]> MyPrimaryList = new List<String[]>();
List<String[]> MySecondaryList = new List<String[]>();

String arrayList = "one,two,three,four,five";
String[] array = arrayList.Split(',');
String[] array2 = new string[5];

Array.Copy(array, array2, 5);

MyPrimaryList.Add(array);
MySecondaryList.Add(array2);

MyPrimaryList[0][0] += "half";

Console.WriteLine(MyPrimaryList[0][0]);
Console.WriteLine(MySecondaryList[0][0]);

这个函数需要输入源数组,目标数组以及长度——请注意检查数组边界。

执行结果如下:

onehalf
one

由于每个列表现在都持有对不同数组的引用,因此您可以独立地操作数组项。


9
您将同一数组实例添加到了两个列表中,因此它们指向相同的内存结构。
如果您想使它们独立,则需要克隆它们;从我的角度来看,一个快速的方法是使用 LINQ,在其中一个列表中使用 list.Add(array.ToArray())

1
不需要.Select(x => x),因为string[]已经实现了IEnumerable<string> - Eren Ersönmez
@Eren,你是对的,我这样做是因为我不确定在数组上调用ToArray是否会返回一个新副本。但我检查过了,它确实是这样工作的。 - Sebastian Piu

7

数组是引用对象,因此您正在修改内存中的同一集合。您所做的就是向相同的结构添加指针,

请查看此文档

将数组作为参数传递(C#编程指南)

您需要对数组进行深度复制以获得所需的自主权。

您可以使用 Array.Copy 进行此操作


0

针对每个列表,您都应该创建一个数组,因为现在您正在指向相同的内存结构

正确的代码应该是:

List<String[]> MyPrimaryList = new List<String[]>();
List<String[]> MySecondaryList = new List<String[]>();
String[] array;
String[] secondaryArray;

String arrayList = "one,two,three,four,five";
array = arrayList.Split(',');
secondaryArray = arrayList.Split(',');

MyPrimaryList.Add(array);
MySecondaryList.Add(secondaryArray);

MyPrimaryList[0][0] += "half";

现在你的第二个列表将有"one"而不是"onehalf"作为第一个元素


0

如上所述,数组是引用类型,因此两个列表将指向同一个数组


要解决您的问题,请使用Clone方法。

MyPrimaryList.Add((String[])array.Clone());
MySecondaryList.Add((String[])array.Clone());

虽然它会对该数组进行浅复制,但在您的情况下很合适


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