更快地填充ObservableCollection

时间:2014-02-27 22:33:25

标签: c# windows-phone-7

我认为这两个代码片段也是如此。我想知道哪一个更快,为什么?其中一个比另一个快得多?

ObservableCollection<Something> CollectionToFill;
ObservableCollection<Something> SourceCollection;

第一个:

CollectionToFill = new ObservableCollection<Something>(SourceCollection.Where(item => item.Name.Equals("ABC")).Select(item => item));

第二个:

foreach (var item in SourceCollection)
{
    if (item.Name.Equals("ABC"))
    {
        CollectionToFill.Add(item);
    }
}

1 个答案:

答案 0 :(得分:3)

你应该知道,这两个做不同的事情。第一个创建一个新集合并替换旧集合的引用。第二个添加项目到现有的集合。听起来可能一样,但事实并非如此。但无论如何。

第一个会更快,因为它不会在每个元素之后引发事件。

Add在内部使用InsertItem,如下所示:

protected override void InsertItem(int index, T item)
{
    this.CheckReentrancy();
    base.InsertItem(index, item);
    this.OnPropertyChanged("Count");
    this.OnPropertyChanged("Item[]");
    this.OnCollectionChanged(NotifyCollectionChangedAction.Add, item, index);
}

base.InsertItem声明为:

protected virtual void InsertItem(int index, T item)
{
    this.items.Insert(index, item);
}

如您所见,添加项目时会引发3个事件。

构造函数使用CopyFrom方法将项​​直接添加到基础集合中,而不会引发任何事件:

public ObservableCollection(IEnumerable<T> collection)
{
    if (collection == null)
    {
        throw new ArgumentNullException("collection");
    }
    this.CopyFrom(collection);
}

private void CopyFrom(IEnumerable<T> collection)
{
    IList<T> items = base.Items;
    if (collection != null && items != null)
    {
        using (IEnumerator<T> enumerator = collection.GetEnumerator())
        {
            while (enumerator.MoveNext())
            {
                items.Add(enumerator.Current);
            }
        }
    }
}