关于 IEnumerable的奇怪问题收藏
我有以下代码:
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 方法时确实有。
这个问题确实困扰了我好久,有谁知道吗?非常感谢。
I have following code:
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);
}
The weird thing is after the BuildTreeView returns, the first element of rootTreeItems doesn't have any children nodes, while it really has when debugging into the BuildTreeView method.
This problem really confused me for quite a long time, any one has any idea? thanks so much.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您很可能遇到
IEnumerable
的延迟执行问题。要记住的是您的IEnumerable; rootTreeItems
不是一个列表,而是一个承诺,每次被要求时都会获得一个列表。因此,如果
BuildRootTreeItems()
使用 LINQ 查询创建IEnumerable
并且不会强制使用.ToList()< 执行查询/code> 或
.ToArray()
然后每次使用rootTreeItems
时都会在其中重新执行查询BuildRootTreeItems()
调用
rootTreeItems.ElementAt(0)
将导致查询执行。如果稍后您尝试再次调用rootTreeItems.ElementAt(0)
,那么您将重新执行查询并返回第一个TreeItem
的不同实例。尝试像这样更改第一行:
这会强制执行并防止稍后重新执行。我敢打赌你的问题就会消失。
You're most likely hitting a deferred execution issue with
IEnumerable<>
. The thing to remember is that yourIEnumerable<TreeItem> rootTreeItems
is not a list, instead it is a promise to get a list each and every time it is asked to do so.So, if
BuildRootTreeItems()
creates theIEnumerable<TreeItem>
using a LINQ query and it doesn't force the execution of the query using.ToList()
or.ToArray()
then each time that you userootTreeItems
you are re-executing the query insideBuildRootTreeItems()
Calling
rootTreeItems.ElementAt(0)
will cause the query to execute. If later you try to callrootTreeItems.ElementAt(0)
again then you are re-executing the query and getting back a different instance of the firstTreeItem
.Try changing the first line like so:
This forces the execution and will prevent re-execution later. I'll bet your problem goes away.
您的 BuildRootTreeItems() 方法有可能返回 IEnumerable 接口,该接口的元素是通过yield 语句创建的,或者如 Gabe 在上面的评论中提到的 IEnumerable 的实现,它是通过包含 Select 方法的 Linq 表达式链创建的。
这可能会导致每次访问任何元素时重新创建 IEnumerable 的元素,或者使用 Linq 表达式或 foreach 语句进行迭代。
There is possibility what your BuildRootTreeItems() method returns IEnumerable interface which elements are created via yield statement or as Gabe mentioned in comment above an implementation of IEnumerable which is created via Linq expressions chain containing Select method.
This can lead to recreating elements of IEnumerable on each access to any element from enumeration or iterating via it using Linq expressions or foreach statement.
我会更简单:
也可能会发生这种情况,
如果A) TreeItem 是值类型(结构)
B) TreeItem.TreeItems 返回一个新集合,
但仅从提供的代码很难推断出其正确性。
I would go simplier:
This also could happen if
A) TreeItem is a value type(struct)
B) TreeItem.TreeItems returns a new collection
But correctness of this is difficult to deduct just from code provided.