Concat causes stack overflow if called multiple times

断了今生、忘了曾经 提交于 2021-01-28 12:12:46

问题


Application accidentally crashed with stack overflow error. After research I found that the reason of crash is following code:

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

This is concatenation of multiple IEnumerables. Application crashed when items contained 10,000 elements.

SelectMany fixed this issue. But still...

Why Concat extension causes stack overflow here?


回答1:


Remember that the result of Concat is not a collection - it's a query.

So your "result" is effectively

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

When the nested queries are generated it causes a stack overflow.

Another option would be to create a list and add to it each time:

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

Which is essentially what SelectMany does (but with a deferred enumerator, not a List):

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



回答2:


When you ask the 10,000th concat to get its result it'll ask the 9,999th concat operation for its result, with the intention of yielding a few more values after it's done, and then then 9,999th concat operation will ask the 9,998th concat for its result, which will ask the 9,997th concat for its result, and eventually you either get down to the 1st concat, or you run out of stack space.

As you mentioned right in the question, SelectMany is the correct operation to flatten a sequence of sequences.



来源:https://stackoverflow.com/questions/26065930/concat-causes-stack-overflow-if-called-multiple-times

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!