集合上的 Clear 方法是否会释放事件订阅?
我有一个集合
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);
}
}
我希望这里的一位 .NET C# 专家可以为我解决这个问题,或者告诉我我做错了什么。
I have a collection
private ObservableCollection<Contact> _contacts;
In the constructor of my class I create it
_contacts = new ObservableCollection<Contact>();
I have methods to add and remove items from my collection. I want to track changes to the entities in my collection which implement the IPropertyChanged interface so I subscribe to their PropertyChanged event.
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);
}
When I remove an entity from the collection, I unsubscribe from the PropertyChanged event. I am told this is to allow the entity to be garbage collected and not create memory issues.
public void RemoveContact(Contact contact)
{
((INotifyPropertyChanged)contact).PropertyChanged -= Contact_PropertyChanged;
_contacts.Remove(contact);
}
So, I hope this is all good. Now, I need to clear the collection in one of my methods. My first thought would be to call _contacts.Clear()
. Then I got to wondering if this releases those event subscriptions? Would I need to create my own clear method? Something like this:
public void ClearContacts()
{
foreach(Contact contact in _contacts)
{
this.RemoveContact(contact);
}
}
I am hoping one of the .NET C# experts here could clear this up for me or tell me what I am doing wrong.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
Clear() 不会删除事件处理程序。 (另请注意,调用 Clear() 不会像 Add() 和 Remove() 那样触发 CollectionChanged 事件。)
Clear() does not remove event handlers. (Note also, that calling Clear() does not trip a CollectionChanged event as Add() and Remove() do.)
您可以为
ObservableCollection
的CollectionChanged
事件提供一个处理程序,这对于在项目事件处理程序被删除时取消挂钩非常有效,并且当您执行Clear
,但问题是e.OldItems
集合在Clear()
上将为 null。因此,同意@Michael,要做你想做的事情,你必须实现你自己的 Clear 方法,也许作为扩展方法:
在你的clear函数中,你可以在调用常规
之前迭代项目并清除事件处理程序Clear() 函数。
You could have a handler for the
CollectionChanged
event of theObservableCollection
, this will work well for unhooking the item event handlers when they are removed and that does get fired when you do aClear
, but the problem is thee.OldItems
collection will be null upon theClear()
.So to agree with @Michael, to do what you want you will have to implement your own Clear method, maybe as an extension method:
in your clear function you could iterate over the items and clear the event handlers before calling the regular
Clear()
function.Clear()
不会释放这些事件订阅。最好使用您自己的 Clear 方法来迭代集合,删除事件处理程序,然后在集合上调用
Clear()
。这样做而不是为每个项目调用
Remove()
的原因是,Remove()
在内部迭代集合以查找项目的索引如果集合中有大量项目,您正在删除,性能可能会受到影响。Clear()
will not release those event subscriptions.It would probably be best to your own Clear method that iterates over the collection removing the event handlers and then calls
Clear()
on the collection.The reason to do this, instead of calling
Remove()
for each item is that, internally,Remove()
iterates over the collection in order to find the index of the item you are removing and performance could suffer if there are a large number of items in the collection.以下是来自 Reflector 的代码:
它检查以确保其中一个事件处理程序没有在循环中调用它,调用基础
Collection
的Clear
函数,通知通知订阅者属性已更改,最后通知订阅者集合已更改。它在任何时候都不会清除任何一个事件处理程序。
Here's the code from Reflector:
It checks to make sure that one of the event handlers hasn't called it in a loop, calls the base
Collection
'sClear
function, notifies the subscribers that properties have changed, and finally notifies subscribers that the collection has changed.At no point does it clear either of the event handlers.