У меня есть набор
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 здесь мог разрешить это для меня или сказать мне, что я делаю неправильно.
Clear () не удаляет обработчики событий. (Также обратите внимание, что вызов Clear () не вызывает событие CollectionChanged, как это делают Add () и Remove ().)
Вот код от Reflector:
protected override void ClearItems()
{
this.CheckReentrancy();
base.ClearItems();
this.OnPropertyChanged("Count");
this.OnPropertyChanged("Item[]");
this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
Он проверяет, чтобы убедившись, что один из обработчиков событий не вызвал его в цикле, вызывает функцию Clear
базы Collection
, уведомляет подписчиков об изменении свойств и, наконец, уведомляет подписчиков, что коллекция изменилась.
Ни в коем случае не очищается ни один из обработчиков событий.
Clear()
не освободит эти подписки на события.
Вероятно, лучше всего было бы использовать собственный метод Clear, который итерирует коллекцию, удаляя обработчики событий, а затем вызывает Clear()
на коллекции.
Причина сделать это вместо вызова Remove()
для каждого элемента в том, что внутри Remove()
выполняется итерация по коллекции, чтобы найти индекс элемента, который вы удаляете, и производительность может пострадать, если в коллекции большое количество элементов.
У вас может быть обработчик для события 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 ()
.