开发者

Weird issue about IEnumerable<T> collection

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 debuggi开发者_JAVA百科ng into the BuildTreeView method.

This problem really confused me for quite a long time, any one has any idea? thanks so much.


You're most likely hitting a deferred execution issue with IEnumerable<>. The thing to remember is that your IEnumerable<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 the IEnumerable<TreeItem> using a LINQ query and it doesn't force the execution of the query using .ToList() or .ToArray() then each time that you use rootTreeItems you are re-executing the query inside BuildRootTreeItems()

Calling rootTreeItems.ElementAt(0) will cause the query to execute. If later you try to call rootTreeItems.ElementAt(0) again then you are re-executing the query and getting back a different instance of the first TreeItem.

Try changing the first line like so:

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

This forces the execution and will prevent re-execution later. I'll bet your problem goes away.


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.


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜