繁体   English   中英

关于IEnumerable的奇怪问题 <T> 采集

[英]Weird issue about IEnumerable<T> collection

我有以下代码:

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方法时确实有。

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

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

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

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

尝试更改第一行,如下所示:

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

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

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

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

我会更简单:

如果这也可能发生

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

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

但是,仅通过提供的代码难以推断出这种正确性。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM