如果多次调用,Concat会导致堆栈溢出

时间:2014-09-26 18:20:04

标签: c# .net linq concatenation stack-overflow

应用程序意外崩溃,堆栈溢出错误。经过研究,我发现崩溃的原因是遵循以下代码:

foreach (var item in items)
{
    result = result.Concat(item.Data);
}

这是多个IEnumerable的串联。当items包含10,000个元素时,应用程序崩溃。

SelectMany解决了这个问题。但还是......

为什么Concat扩展导致堆栈溢出?

2 个答案:

答案 0 :(得分:8)

请注意,Concat的结果不是集合 - 它是查询

所以你的结果"实际上是

Enumerable.Concat(item10000.Data, 
                  Enumerable.Concat(item9999.Data, 
                                  ....
                                    Enumerable.Concat(item2.Data, 
                                                      item1.Data))));

生成嵌套查询时会导致堆栈溢出。

另一个选择是创建一个列表并每次添加它:

var list = new List<something>();
foreach (var item in items)
{
    list.AddRange(item.Data);
}

这基本上是SelectMany的作用(但是使用延迟的枚举器,而不是List):

result = items.SelectMany(item => item.Data);

答案 1 :(得分:1)

当你要求第10,000个concat得到它的结果时,它会询问第9,999次连续操作它的结果,意图在它之后产生更多的值。&#39;完成后,然后第9,999次concat操作将询问9,998th concat的结果,它会询问9,997th concat的结果,最后你要么得到第1次concat,要么你的堆栈空间不足。

正如您在问题中所提到的那样,SelectMany是压缩序列序列的正确操作。