关于IEnumerable <t>集合的奇怪问题</t>

时间:2011-08-25 04:03:40

标签: c# ienumerable elements

我有以下代码:

IEnumerable<TreeItem> rootTreeItems = BuildRootTreeItems();

BuildTreeView(rootTreeItems.ElementAt(0));

private static void BuildTreeView(TreeItem treeItem)
    {
        TreeItem subMenuTreeItem = new TreeItem();
        subMenuTreeItem.Header = "1";

        TreeItem subMenuTreeItem2 = new TreeItem();
        subMenuTreeItem.Header = "2";

        treeItem.TreeItems.Add(subMenuTreeItem);
        treeItem.TreeItems.Add(subMenuTreeItem2);
    }

奇怪的是,在BuildTreeView返回之后,rootTreeItems的第一个元素没有任何子节点,而它在调试BuildTreeView方法时确实有。

这个问题让我困惑很长一段时间,任何人都有任何想法?非常感谢。

3 个答案:

答案 0 :(得分:3)

您最有可能遇到IEnumerable<>的延迟执行问题。要记住的是,你的IEnumerable<TreeItem> rootTreeItems不是一个列表,而是承诺在每次要求时都会获得一个列表。

因此,如果BuildRootTreeItems()使用LINQ查询创建IEnumerable<TreeItem>,并且它不会强制使用.ToList().ToArray()执行查询,那么每次都是使用rootTreeItems您正在BuildRootTreeItems()

中重新执行查询

调用rootTreeItems.ElementAt(0)将导致查询执行。如果稍后您尝试再次调用rootTreeItems.ElementAt(0),那么您将重新执行查询并返回第一个TreeItem的其他实例。

尝试更改第一行:

IEnumerable<TreeItem> rootTreeItems = BuildRootTreeItems().ToArray();

这会强制执行并阻止以后重新执行。我打赌你的问题会消失。

答案 1 :(得分:1)

你的BuildRootTreeItems()方法有可能返回IEnumerable接口,哪些元素是通过yield语句创建的,或者是Gabe在上面的注释中提到的IEnumerable实现,它是通过包含Select方法的Linq表达式链创建的。

这可以导致在枚举中对任何元素的每次访问中重新创建IEnumerable的元素,或者使用Linq表达式或foreach语句通过它重复迭代。

答案 2 :(得分:0)

我会更简单:

如果

,也可能发生这种情况

A)TreeItem是一个值类型(struct)

B)TreeItem.TreeItems返回一个新集合

但这样做的正确性很难从提供的代码中扣除。