0

在以下方法中,当我将IEnumerable结果复制到带有 的列表时ToList(),不会在的构造函数中调用终结器,并且视图模型仅在程序关闭时才最终确定:ObservableCollectionIListIDisposable

private void ReadHeaders()
{
    IList<PlanningGridHeaderVM> viewModelSet =
        (from header in _planningGridService.ReloadHeaders().OrderBy(x => x.PlanNumber)
         select new PlanningGridHeaderVM((PlanningGridHeader)header)).ToList();

    foreach (PlanningGridHeaderVM headerVM in viewModelSet)
    {
        ItemEditedEventManager.AddHandler(headerVM, OnItemEdited);
        PropertyChangedEventManager.AddHandler(headerVM, OnPropertyChanged, string.Empty);
    }

    this.ViewModels = new ObservableCollection<PlanningGridHeaderVM>(viewModelSet);
    CollectionChangedEventManager.AddHandler(this.ViewModels, this.OnCollectionChanged);
}

然而,当我IEnumerable直接在ObservableCollection's 的IEnumerable构造函数中使用结果时,我的 Debug 输出通知我所有IDisposable视图模型项都由GC 完成(这让我感到困惑)。

尽管如此,我仍然在屏幕上获得了所需的集合,并且在程序关闭后,它们都再次完成(这一次,正如预期的那样):

private void ReadHeaders()
{
    IEnumerable<PlanningGridHeaderVM> viewModelSet =
        (from header in _planningGridService.ReloadHeaders().OrderBy(x => x.PlanNumber)
         select new PlanningGridHeaderVM((PlanningGridHeader)header));

    foreach (PlanningGridHeaderVM headerVM in viewModelSet)
    {
        ItemEditedEventManager.AddHandler(headerVM, OnItemEdited);
        PropertyChangedEventManager.AddHandler(headerVM, OnPropertyChanged, string.Empty);
    }

    this.ViewModels = new ObservableCollection<PlanningGridHeaderVM>(viewModelSet);
    CollectionChangedEventManager.AddHandler(this.ViewModels, this.OnCollectionChanged);
}

为什么?两者的 MSDN 页面(这里这里)都说“元素被复制到 ObservableCollection 上的顺序与集合的枚举器读取它们的顺序相同。”

4

1 回答 1

2

在第二种情况下,您实际上对查询进行了两次评估。一次在您使用时foreach,然后在另一次您创建ObservableCollection. 您最终会得到两组不同的对象,您可以通过在PlanningGridHeaderVM构造函数中添加一些调试信息来验证它们。

第一次迭代查询结果不会主动完成它 - 没有这样的概念。AddHandler但是,除非您的方法保留对它们的引用,否则返回的对象将立即有资格进行垃圾回收。

在第一种情况下,您只评估一次查询,因为ToList()实现查询。它基本上是接受查询,评估它并记住结果 - 所以当你迭代它foreach然后ObservableCollection从中创建一个时,这两个循环都将在同一个对象集合上运行。

于 2013-11-04T07:02:09.177 回答