我在在线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 :(" )


请注意,这与垃圾回收无关-实际上,如果“带有事件的事物”仍通过委托知道它,则无法进行垃圾回收。

10-06 01:10