C# - =运算符多次取消订阅单个事件

时间:2016-10-12 18:41:47

标签: c# events unsubscribe

在C#5中,取消订阅事件时, - =运算符的行为是什么。

假设多次订阅同一事件对此应用程序逻辑有效,如下所示:

Property_Saved += Property_Saved_Handler;
Property_Saved += Property_Saved_Handler;
Property_Saved += Property_Saved_Handler;

现在我们订阅了三次。

取消订阅以下一行代码后:

Property_Saved -= Property_Saved_Handler;

剩下多少订阅? 2?没有? ...?

4 个答案:

答案 0 :(得分:12)

之后剩下两个。每个Array.Sort()仅删除一个订阅。至少,如果它仅使用常规委托来支持该事件,就属于这种情况。

您可以轻松地看到这一点,而不会涉及事件:

-=

严格地说,事件订阅可以做任何事情。你可以实现这样的事件:

using System;

public class Program
{
    public static void Main(string[] args)
    {
        Action action = () => Console.WriteLine("Foo");
        // This is a stand-in for the event.
        Action x = null;
        x += action;
        x += action;
        x += action;
        x -= action;
        x(); // Prints Foo twice
    }
}

但通常事件只委托给Delegate.CombineDelegate.Remove,这些方法private EventHandler weirdEvent; public event EventHandler WeirdEvent { add { weirdEvent += value; } // Subscribe as normal remove { weirdEvent = null; } // I'm bored with *all* the handlers } +=是C#中的语法糖。

我的article on events and delegates包含有关组合和删除的确切内容的更多详细信息。

答案 1 :(得分:2)

private void button1_Click(object sender, EventArgs e)
{
  // set breakpoint
}

this.button1.Click += new System.EventHandler(this.button1_Click);
this.button1.Click += new System.EventHandler(this.button1_Click);
this.button1.Click += new System.EventHandler(this.button1_Click);
this.button1.Click -= new System.EventHandler(this.button1_Click);

调用click事件将显示断点被击中两次。

答案 2 :(得分:1)

使用GetInvocationList

进行自己的测试
public delegate void MyEventHandler(string s);
public event MyEventHandler MyEvent;
MyEventHandler @event = s => { };

MyEvent += @event;
Console.WriteLine(MyEvent.GetInvocationList().Length);

MyEvent += @event;
Console.WriteLine(MyEvent.GetInvocationList().Length);

MyEvent -= @event;
Console.WriteLine(MyEvent.GetInvocationList().Length);

这将打印

1
2
1

答案 3 :(得分:0)

这也应该是安全的。

Property_Saved += Property_Saved_Handler;
Property_Saved -= Property_Saved_Handler;
Property_Saved -= Property_Saved_Handler;