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直接使用すると、デバッグ出力で、その時点ですべてのビューモデル項目がGC によってファイナライズされていることが通知されます(これが私を困惑させます)。ObservableCollectionIEnumerableIDisposable

それにもかかわらず、私はまだ目的のコレクションを画面に表示し、プログラムを閉じると、それらはすべて再びファイナライズされます(今回は予想どおり):

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 ページ ( hereおよびhere ) には、「要素は、コレクションの列挙子によって読み取られるのと同じ順序で ObservableCollection にコピーされます」と記載されています。

4

1 に答える 1

2

2 番目のケースでは、実際にはクエリを 2 回評価しています。を使用するときforeachに 1 回、次に を作成するときにObservableCollection. PlanningGridHeaderVM最終的に、コンストラクターにデバッグ情報を追加することで検証できる、2 つの異なるオブジェクトのセットができあがります。

クエリ結果を最初に反復処理しても、積極的にファイナライズするわけではありません。そのような概念はありません。AddHandlerただし、メソッドがオブジェクトへの参照を保持しない限り、返されたオブジェクトはすぐにガベージ コレクションの対象になります。

ToList()最初のケースでは、クエリを実体化するため、クエリを 1 回だけ評価します。基本的には、クエリを取得して評価し、結果を記憶します。そのため、それを反復処理してからforeachを作成するObservableCollectionと、これらのループの両方が同じオブジェクトのコレクションに対して動作します。

于 2013-11-04T07:02:09.177 に答える