我在在线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." );
}
}
谢谢。
最佳答案
您将必须控制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 :(" )
请注意,这与垃圾回收无关-实际上,如果“带有事件的事物”仍通过委托知道它,则无法进行垃圾回收。