字符串数组列表 (List<string[]>)

8

我遇到了一个奇怪的问题,我的所有字符串数组在列表中都具有相同的值。

这是我的代码:

List<string[]> map_data = new List<string[]>();
string[] map_data_array = new string[11];

for(int i = 0; i < 2000; i++)
{
    map_data_array = PopulateDataFromFile(); // it returns different data every call
    map_data.Add(map_data_array); // store to List
}

map_data_array始终包含不同的数据,我通过在那里放置断点并检查它来验证了这一点。

问题是map_data的所有元素具有相同的值。而且这个值是来自函数PopulateDataFromFile在i等于1999时的数据。

我做错了什么? :/


9
请贴出PopulateDataFromFile()的代码。 - aiapatag
在立即窗口中尝试输入 map_data[0] == map_data[1999],如果返回 true,则您正在添加相同的数组2000次(也就是说,如果 PopulateDataFromFile() 返回相同的数组,则返回相同的内容)。如果返回 false,则 PopulateDataFromFile() 每次都会返回一个新的数组,但内容相同。 - Rune FS
@ShadowWizard 好的,我注意到了内联代码的问题,我保证不会再这样做了;-)但是我从来没有改过标题... - Gauthier Boaglio
@Golgauth 好的,但是我评论中的第二部分仍然成立。 - Shadow The Spring Wizard
PopulateDataFromFile(); 一次性返回所有数据,数组会尽可能地存储,例如前12个元素。请查看我的答案。 - DGibbs
显示剩余2条评论
4个回答

12

只有当您将相同的数组放入列表中时才会发生这种情况。由于您没有提供 PopulateDataFromFile 的代码,因此我们只能猜测会发生什么。请确保该函数每次返回一个使用 new 创建的单独的数组。


1
谢谢,我已经在“全局”范围内声明了“map_data_array”。 - tilenslo
但是为什么会发生这种情况呢?列表实际上是“链接”对象而不是保存/复制该对象具有的数据吗? - tilenslo
1
@tilenslo 这是因为 PopulateDataFromFile(); 可能在每次迭代中返回相同的数据。 - DGibbs
没错!考虑到我们这里只有少数智力,这是一个很好的综合。 - Gauthier Boaglio
1
@svick 嗯,如果你在 PopulateDataFromFile() 返回后查看它返回的数组,似乎每次返回的数据都不同,为什么我很难相信呢?由于我们没有该方法的具体代码,我们只能推测其实现方式。 - DGibbs
显示剩余5条评论

1

由于PopulateDataFromFile();似乎一次性返回所有数据(或者尽可能多的数据以适应数组),因此您需要分块处理数据。使用扩展方法,您可以像这样做:

List<string[]> map_data = new List<string[]>();
foreach (var batch in PopulateDataFromFile().Batch(11))
{
       map_data.Add((batch.ToArray());
}

扩展方法:-
public static IEnumerable<IEnumerable<T>> Batch<T>(this IEnumerable<T> items, int batchSize)
{
     return items.Select((item, inx) => new { item, inx })
                 .GroupBy(x => x.inx / batchSize)
                 .Select(g => g.Select(x => x.item));
}

我真的不明白分块处理如何有所帮助。为什么是11?为什么不是10000000? - svick
可能与以下代码有关:string[] map_data_array = new string[11];... 我觉得 PopulateDataFromFile(); 可能会返回所有内容,但如果您有不同意见,请随时提出 :) - DGibbs
没错,我没有意识到这一点。但这意味着你的代码甚至更加没有意义,因为它总是会返回一个单一的批次。 - svick
怎么可能?考虑到集合大小为2000,哪个星球上会返回一个单一的批次呢? - DGibbs
我假设PopulateDataFromFile()函数始终返回一个有11个元素的数组。但无论如何,我仍然看不到任何分批处理数据可以解决问题的情况。 - svick
你知道人们常说的关于假设的话吗? - DGibbs

0

PopulateDataFromFile()函数返回一个具有相同值的字符串数组。


问题说得不同:“map_data_array始终具有不同的数据”。 - svick

-5
在循环中,每次只需更改map_data_array的地址,因此值始终会更改为从方法调用获得的新数据。每次重新初始化字符串数组都会有所帮助。应该看起来像这样。
    for(int i = 0; i < 2000; i++)
    {
         string[] map_data_array = PopulateDataFromFile(); // it returns different data every call
         map_data.Add(map_data_array); // store to List
    } 

如果这让你感到困惑,你可以简单地这样做:

    for(int i = 0; i < 2000; i++)
    {             
         map_data.Add(PopulateDataFromFile()); // store to List
    } 

2
我不理解这里的答案... 它本质上与 OP 所做的相同。 - aiapatag
抱歉,那是错误的。只有函数的返回值决定了存储在列表中的内容,无论您将其暂时存储在哪个变量中(只要您不进行复制)。 - nvoigt
你是说如果你在循环外声明 map_data_array,然后改变它,列表中的值也会改变吗?这显然是不正确的。 - svick
那不会改变任何东西。声明并不确定存储位置,只有 new 可以。 - Rune FS
是的,你必须确保从方法(PopulateDataFromFile)返回的值始终是一个新对象,而不仅仅是更改现有对象。 - srsyogesh

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