Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/327.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 代表,活动-如何取消订阅?_C#_Events_Scope_Delegates - Fatal编程技术网

C# 代表,活动-如何取消订阅?

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

我在一本在线C#book上找到了以下委托/事件示例。但是我错过的是当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对象已经超出范围,我认为它应该已经在字节涅盘中了

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总是创建一个新的处理程序。因此,取消订阅部分将抛出。