C# 代表,活动-如何取消订阅?
我在一本在线C#book上找到了以下委托/事件示例。但是我错过的是当MailWatch对象死亡时取消订阅-什么是取消订阅的正确方法C# 代表,活动-如何取消订阅?,c#,events,scope,delegates,C#,Events,Scope,Delegates,我在一本在线C#book上找到了以下委托/事件示例。但是我错过的是当MailWatch对象死亡时取消订阅-什么是取消订阅的正确方法 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; class NewEmailEventArgs : EventArgs { public NewEmailEventArgs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
class NewEmailEventArgs : EventArgs
{
public NewEmailEventArgs ( string subject, string message )
{
this.subject = subject;
this.message = message;
}
public string Subject { get { return ( subject ); } }
public string Message { get { return ( message ); } }
string subject;
string message;
}
class EmailNotify
{
public delegate void NewMailEventHandler ( object sender, NewEmailEventArgs e );
public event NewMailEventHandler OnNewMailHandler;
protected void OnNewMail ( NewEmailEventArgs e )
{
if ( OnNewMailHandler != null )
OnNewMailHandler( this, e );
}
public void NotifyMail ( string subject, string message )
{
NewEmailEventArgs e = new NewEmailEventArgs( subject, message );
OnNewMail( e );
}
}
class MailWatch
{
public MailWatch ( EmailNotify emailNotify )
{
this.emailNotify = emailNotify;
emailNotify.OnNewMailHandler += new EmailNotify.NewMailEventHandler( IHaveMail );
}
void IHaveMail ( object sender, NewEmailEventArgs e )
{
Console.WriteLine( "New Mail:", e.Subject, e.Message );
}
EmailNotify emailNotify;
}
class Test
{
public static void Main ()
{
EmailNotify emailNotify = new EmailNotify();
MailWatch mailWatch = new MailWatch( emailNotify );
emailNotify.NotifyMail( "Hello!", "Welcome to Events!!!" )
}
}
为什么MailWatch对象会收到第二封NotifyMail?MailWatch对象已经超出范围,我认为它应该已经在字节涅盘中了
class Test
{
public static void Main ()
{
EmailNotify emailNotify = new EmailNotify();
{
MailWatch mailWatch = new MailWatch( emailNotify );
emailNotify.NotifyMail( "1!", "At live." );
}
emailNotify.NotifyMail( "2!", "Still alive." );
}
}
谢谢。要取消订阅,请将订阅的
+=
更改为-=
:
emailNotify.OnNewMailHandler -= EmailNotify.NewMailEventHandler;
有关更多信息,您可以查看MSDN。假设字节Nirvana意味着垃圾收集-不,它还不在那里,它的实例成员在事件处理程序中使用,因此只要订阅了该处理程序,它就会保持活动状态。只有从事件中取消订阅处理程序后,才能对对象进行垃圾收集。您必须控制
MailWatch
的生存期。理想的方法是通过IDisposable
,并在处置时让其自行取消订阅:
class MailWatch : IDisposable
{
public void Dispose()
{
emailNotify?.OnNewMailHandler -= IHaveMail;
emailNotify = null;
}
并确保Dispose()
实例-理想情况下通过使用
:
using(MailWatch mailWatch = new MailWatch( emailNotify ))
{
emailNotify.NotifyMail( "Hello!", "Welcome to Events!!!" )
// ..
}
emailNotify.NotifyMail( "Oh no", "No-one is listening to me :(" )
请注意,这与垃圾收集无关——事实上,如果“事件中的事物”仍然通过委托知道它,则不能对其进行垃圾收集。事件订阅+=或取消订阅-=仅使用的那些
emailNotify.OnNewMailHandler += new EmailNotify.NewMailEventHandler( IHaveMail );
就是订阅活动,
emailNotify.OnNewMailHandler -= new EmailNotify.NewMailEventHandler( IHaveMail );
这就是取消订阅事件。您是否尝试过取消订阅操作员
-=
?可能重复非常小的方便调整:emailNotify.OnNewMailHandler+=IHaveMail代码>-含义相同;只是更容易输入和阅读我不认为这样行,你必须保存一个对eventhandler的引用,这样你就可以完全取消订阅。如果您在取消订阅时创建了一个新的事件处理程序,但没有任何更改(删除一些不存在的内容),那么只需var handler=neweventhandler(方法)代码>someEvent+=handler代码>/*做一些事情*/
someEvent-=handler代码>@Stefan你没有,我有;)这很有效。只剩下范围问题-如果我只是将那行代码放入解构器中,它将不起作用。它与-=new-EmailNotify.NewMailEventHandler(IHaveMail)
一起工作!是的,我是说垃圾。我得去拿垃圾东西。。。它有点不同于C和C++…你应该得到第二个复选标记。THXGood,这解决了两个问题。取消订阅和作用域问题。这不会作为新的EmailNotify工作。NewMailEventHandler总是创建一个新的处理程序。因此,取消订阅部分将抛出。