嵌套查询的StackOverflowException,小项目计数

时间:2013-12-10 12:49:12

标签: c# .net linq stack-overflow

我找到了一些类似标题的帖子,但似乎都没有一个合适的答案。 一个人提到了4.0之前的.NET版本中的一个错误 - 我使用的是4.0,所以这不应该是它。

考虑一下这个例子: 我正在尝试创建类Part的实例集合,它们不属于任何类PartGroup的实例。

Func<Part,bool> hasGroup = P => partColl.Groups.Any( G => G.Parts.Contains(P) );
var groupless = partColl.Parts.Where( P => ! hasGroup(P) );

partColl是实现属性组和部件的类的实例,每个IEnumerable<T>其中T分别是PartGroup或Part,内部实现为List<T>。 partColl.Parts包含现有的所有部分。 class Group具有属性IEnumerable<Part> Parts,列出了对属于该组的部分的引用。

在我目前的程序中,有27个部分和5个组,元素没有重叠。 如果事情不是犯规的话,尽管有二次复杂性,但没有什么可以给筹码带来麻烦 当我运行它时,它将在hasGroup上的所述异常崩溃。

我错过了什么?


修改 一个小细节滑落了​​我在这里提出的抽象: 与PartCollection的两个属性不同,IEnumerable PartGroup.Parts没有List支持,它是一个带有私有集的自动属性,在c'tor中用传入的IEenumerable初始化。这个IEnumerable背后的实例也是一个列表,每个组都有一个列表,所以我不确定究竟发生了什么。

但是,异常已经消失了:还使用List类型的变量支持该属性,并在构造函数中为其分配:_list = parts.ToList(),其中parts是{{ 1}},作为一个参数传递给ctor。我做ToList只是为了确保它真的是一个列表,而不是一些半生不熟的查询,但它应该,因为在我构建组的地方,每个组的一个新列表在传递之前被分配...

剩下的问题仍然很有趣:发生了什么,为什么自动财产'导致'例外? 我会根据要求发布更多详细信息,但现在要花一点时间。

1 个答案:

答案 0 :(得分:0)

这个小样本不能重现这个问题。

using System;
using System.Linq;
using System.Collections.Generic;
class P
{
    class PartGroup
    {
        public List<Part> Parts { get; private set; }
        public PartGroup()
        {
            Parts = new List<Part>();
        }
    }

    class Part
    {
    }

    class PartCollection
    {
        public List<Part> Parts { get; set; }
        public List<PartGroup> Groups { get; set; }
        public PartCollection()
        {
            Parts = new List<Part>();
            Groups = new List<PartGroup>();
        }
    }

    static void Main()
    {
        var groups = new List<PartGroup> { new PartGroup(), new PartGroup(), new PartGroup(), new PartGroup(), new PartGroup() };
        var partColl = new PartCollection();
        partColl.Parts.Add(new Part());
        partColl.Groups.AddRange(groups);
        for (int i = 0; i < 27; i++)
        {
            var part = new Part();
            groups[i % groups.Count].Parts.Add(part);
            partColl.Parts.Add(part);
        }
        partColl.Parts.Add(new Part());

        Func<Part, bool> hasGroup = P => partColl.Groups.Any(G => G.Parts.Contains(P));
        var groupless = partColl.Parts.Where(P => !hasGroup(P)).ToList();
    }
}