我在在线C#书中找到了以下委托/事件示例。但我想念的是在MailWatch对象死亡时取消订阅 - 取消订阅它的正确方法是什么?
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对象已经超出了范围,我认为它应该已经在Byte-Nirvana中了?
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." );
}
}
感谢。
答案 0 :(得分:1)
要取消订阅,请将订阅的+=
更改为-=
:
emailNotify.OnNewMailHandler -= EmailNotify.NewMailEventHandler;
有关详细信息,请查看MSDN上的How to: Subscribe to and Unsubscribe from Events。
答案 1 :(得分:1)
假设Byte-Nirvana意味着垃圾收集 - 不,它还没有,它的实例成员在事件处理程序中使用,所以只要该处理程序被订阅它就会保持活动状态。只有在您从事件中取消订阅处理程序后,才能对对象进行垃圾回收。
答案 2 :(得分:1)
您必须控制MailWatch
的生命周期。理想的方式是通过IDisposable
,并在处置时取消订阅:
class MailWatch : IDisposable
{
public void Dispose()
{
emailNotify?.OnNewMailHandler -= IHaveMail;
emailNotify = null;
}
并确保Dispose()
该实例 - 最好通过using
:
using(MailWatch mailWatch = new MailWatch( emailNotify ))
{
emailNotify.NotifyMail( "Hello!", "Welcome to Events!!!" )
// ..
}
emailNotify.NotifyMail( "Oh no", "No-one is listening to me :(" )
请注意,这与垃圾收集无关 - 实际上,如果"事件" 不能进行垃圾收集。仍然通过代表了解它。
答案 3 :(得分:0)
活动订阅+ =或取消订阅 - =仅使用
emailNotify.OnNewMailHandler += new EmailNotify.NewMailEventHandler( IHaveMail );
即订阅活动,
emailNotify.OnNewMailHandler -= new EmailNotify.NewMailEventHandler( IHaveMail );
这是取消订阅事件。