Четкий метод на выпуске набора подписки события?

У меня есть набор

private ObservableCollection<Contact> _contacts;

В конструкторе моего класса я создаю его

_contacts = new ObservableCollection<Contact>();

У меня есть методы, чтобы добавить и удалить объекты из моего набора. Я хочу отследить изменения в объектах в моем наборе, которые реализуют интерфейс IPropertyChanged, таким образом, я подписываюсь на их событие PropertyChanged.

public void AddContact(Contact contact)
{
    ((INotifyPropertyChanged)contact).PropertyChanged += new PropertyChangedEventHandler(Contact_PropertyChanged);
    _contacts.Add(contact);
}

public void AddContact(int index, Contact contact)
{
    ((INotifyPropertyChanged)contact).PropertyChanged += new PropertyChangedEventHandler(Contact_PropertyChanged);
    _contacts.Insert(index, contact);
}

Когда я удаляю объект из набора, я отказываюсь от подписки от события PropertyChanged. Мне говорят, что это должно позволить объекту быть собранным "мусор" и не создать проблемы памяти.

public void RemoveContact(Contact contact)
{
    ((INotifyPropertyChanged)contact).PropertyChanged -= Contact_PropertyChanged;
    _contacts.Remove(contact);
}

Так, я надеюсь, что это - вся польза. Теперь, я должен очистить набор в одном из моих методов. Моя первая мысль состояла бы в том, чтобы звонить _contacts.Clear(). Затем я добрался до удивления, если это выпускает те подписки события? Я должен был бы создать свой собственный четкий метод? Что-то вроде этого:

public void ClearContacts()
{
    foreach(Contact contact in _contacts)
    {
        this.RemoveContact(contact);
    }
}

Я надеюсь, что один из экспертов C#.NET здесь мог разрешить это для меня или сказать мне, что я делаю неправильно.

5
задан DaveB 19 March 2010 в 21:32
поделиться

4 ответа

Clear () не удаляет обработчики событий. (Также обратите внимание, что вызов Clear () не вызывает событие CollectionChanged, как это делают Add () и Remove ().)

4
ответ дан 14 December 2019 в 19:09
поделиться

Вот код от Reflector:

protected override void ClearItems()
{
    this.CheckReentrancy();
    base.ClearItems();
    this.OnPropertyChanged("Count");
    this.OnPropertyChanged("Item[]");
    this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}

Он проверяет, чтобы убедившись, что один из обработчиков событий не вызвал его в цикле, вызывает функцию Clear базы Collection , уведомляет подписчиков об изменении свойств и, наконец, уведомляет подписчиков, что коллекция изменилась.

Ни в коем случае не очищается ни один из обработчиков событий.

0
ответ дан 14 December 2019 в 19:09
поделиться

Clear() не освободит эти подписки на события.

Вероятно, лучше всего было бы использовать собственный метод Clear, который итерирует коллекцию, удаляя обработчики событий, а затем вызывает Clear() на коллекции.

Причина сделать это вместо вызова Remove() для каждого элемента в том, что внутри Remove() выполняется итерация по коллекции, чтобы найти индекс элемента, который вы удаляете, и производительность может пострадать, если в коллекции большое количество элементов.

0
ответ дан 14 December 2019 в 19:09
поделиться

У вас может быть обработчик для события CollectionChanged из ObservableCollection , это будет хорошо работать для отключения обработчики событий элементов, когда они удаляются, и это действительно срабатывает, когда вы выполняете Clear , но проблема в том, что коллекция e.OldItems будет иметь значение null после Clear () .

Итак, чтобы согласиться с @Michael, чтобы делать то, что вы хотите, вам нужно будет реализовать свой собственный метод Clear, возможно, как метод расширения:

public static class Extensions
{
    public static void ClearEx(this ObservableCollection<object> collection)
    {
        //custom clear logic...   
    }
}

в вашей функции clear вы можете перебирать элементы и очищать обработчики событий перед вызов обычной функции Clear () .

1
ответ дан 14 December 2019 в 19:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: