Jon*_*n B 49 .net events idisposable unsubscribe
我有一个类来处理来自WinForms控件的事件.根据用户正在做的事情,我正在引用该类的一个实例并创建一个新实例来处理同一事件.我需要先从事件中取消订阅旧实例 - 这很容易.如果可能的话,我想以非专有方式这样做,看起来这是IDisposable的工作.但是,大多数文档仅在使用非托管资源时才建议使用IDisposable,这在此处不适用.
如果我实现IDisposable并取消订阅Dispose()中的事件,我是否会歪曲它的意图?我应该提供一个Unsubscribe()函数并调用它吗?
编辑:这是一些虚拟代码,它显示了我正在做的事情(使用IDisposable).我的实际实现与一些专有数据绑定(长篇故事)有关.
class EventListener : IDisposable
{
private TextBox m_textBox;
public EventListener(TextBox textBox)
{
m_textBox = textBox;
textBox.TextChanged += new EventHandler(textBox_TextChanged);
}
void textBox_TextChanged(object sender, EventArgs e)
{
// do something
}
public void Dispose()
{
m_textBox.TextChanged -= new EventHandler(textBox_TextChanged);
}
}
class MyClass
{
EventListener m_eventListener = null;
TextBox m_textBox = new TextBox();
void SetEventListener()
{
if (m_eventListener != null) m_eventListener.Dispose();
m_eventListener = new EventListener(m_textBox);
}
}
Run Code Online (Sandbox Code Playgroud)
在实际代码中,"EventListener"类涉及更多,每个实例都具有独特的重要性.我在集合中使用它们,并在用户点击时创建/销毁它们.
结论
我接受gbjbaanb的回答,至少目前如此.我觉得使用熟悉的界面的好处超过了在没有涉及非托管代码的情况下使用它的任何可能的缺点(这个对象的用户怎么会知道?).
如果有人不同意 - 请发帖/评论/编辑.如果可以对IDisposable做出更好的论证,那么我将改变接受的答案.
gbj*_*anb 40
是的,去吧.虽然有些人认为IDisposable仅针对非托管资源实现,但事实并非如此 - 非托管资源恰好是最大的胜利,也是实现它的最明显的理由.我认为它获得了这个想法,因为人们无法想到使用它的任何其他原因.它不像一个性能问题的终结器,并且GC不易处理.
在您的dispose方法中添加任何整理代码.它会更清晰,更清晰,更有可能防止内存泄漏,并且比试图记住取消引用更容易正确使用.
IDisposable的目的是让您的代码更好地工作,而无需您进行大量的手动工作.使用它的力量对你有利,并克服一些人为的"设计意图"废话.
我记得当.NET首次出现时,很难说服微软确定最终确定的有用性 - 我们赢得了战斗并说服他们添加它(即使它当时只是一种设计模式),使用它!
Jar*_*Par 13
我的个人投票是使用Unsubscribe方法从事件中删除类.IDisposable是一种用于确定性释放非托管资源的模式.在这种情况下,您不管理任何非托管资源,因此不应实现IDisposable.
IDisposable可用于管理事件订阅,但可能不应该.举个例子,我指向WPF.这是一个充满活动和事件处理程序的图书馆.然而,WPF中几乎没有类实现IDisposable.我认为这表明应该以另一种方式管理事件.
使用IDisposable模式取消订阅事件困扰我的一件事是Finalization问题.
Dispose()函数in IDisposable应该由开发人员调用,但是如果它没有被开发人员调用,那么可以理解GC将调用这个函数(IDisposable至少通过标准模式).但是,在你的情况下,如果你不打电话,Dispose其他人就不会 - 事件仍然存在且强引用使GC无法调用终结器.
在Dispose我看来,()不会自动调用()的事实似乎足以在这种情况下不使用IDisposable.也许它需要一个新的特定于应用程序的接口,该接口说这种类型的对象必须具有一个由GC处理的清理函数.
我认为一次性适用于 GC 无法自动处理的任何事情,并且事件引用在我的书中很重要。这是我想出的一个助手类。
public class DisposableEvent<T> : IDisposable
{
EventHandler<EventArgs<T>> Target { get; set; }
public T Args { get; set; }
bool fired = false;
public DisposableEvent(EventHandler<EventArgs<T>> target)
{
Target = target;
Target += new EventHandler<EventArgs<T>>(subscriber);
}
public bool Wait(int howLongSeconds)
{
DateTime start = DateTime.Now;
while (!fired && (DateTime.Now - start).TotalSeconds < howLongSeconds)
{
Thread.Sleep(100);
}
return fired;
}
void subscriber(object sender, EventArgs<T> e)
{
Args = e.Value;
fired = true;
}
public void Dispose()
{
Target -= subscriber;
Target = null;
}
}
Run Code Online (Sandbox Code Playgroud)
这让您可以编写此代码:
Class1 class1 = new Class1();
using (var x = new DisposableEvent<object>(class1.Test))
{
if (x.Wait(30))
{
var result = x.Args;
}
}
Run Code Online (Sandbox Code Playgroud)
一个副作用是,您不能在事件上使用 event 关键字,因为这会阻止将它们作为参数传递给辅助构造函数,但是,这似乎没有任何不良影响。
| 归档时间: |
|
| 查看次数: |
15276 次 |
| 最近记录: |