The result of a query expression is a query, not the result of the query

This bit me recently. To quote Eric Lippert (last paragraph):

Remember that with LINQ the result of a query expression is a query that can deliver the results when asked, not the results of the query.

This code will result in the PropertyChanged event handler never being called:

    var items = (from item in MethodThatGetsItemsAsEnumerable()
                select new ViewModelEntity(item));

    foreach (var item in items)
    {
        item.PropertyChanged += item_PropertyChanged;
    }

    this.Items = new ObservableCollection<ViewModelEntity>(items);

The correct code is, of course:

    var items = (from item in MethodThatGetsItemsAsEnumerable()
                select new ViewModelEntity(item)).ToList();

    foreach (var item in items)
    {
        item.PropertyChanged += item_PropertyChanged;
    }

    this.Items = new ObservableCollection<ViewModelEntity>(items);

The first code will result in MethodThatGetsItemsAsEnumerable being called twice, once when items is iterated over in the foreach and once when the ObservableCollection is constructed, ergo the item's that had item_PropertyChanged attached have long since disappeared. The ToList() in the second version is the solution as it turns the query into the results of the query.


No Comments