关于IEnumerable收集

本文关键字:收集 IEnumerable 关于 | 更新日期: 2023-09-27 18:06:31

我有以下代码:

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<T>收集

您很可能遇到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返回一个新的集合

但是仅从所提供的代码中很难推断其正确性