C# -= 运算符多次取消订阅单个事件
C# -= operator to unsubscribe from a single event multiple times
在 C# 5 中,取消订阅事件时 -= 运算符的行为是什么。
假设多次订阅同一个事件对于这个应用逻辑是有效的,例如:
Property_Saved += Property_Saved_Handler;
Property_Saved += Property_Saved_Handler;
Property_Saved += Property_Saved_Handler;
现在我们订阅了三遍。
使用以下一行代码取消订阅后:
Property_Saved -= Property_Saved_Handler;
还剩多少订阅? 2? none? ...?
之后还剩下两个。每个 -=
只删除一个订阅。至少,如果它仅使用常规委托来支持事件,情况就是如此。
您可以轻松地看到这一点,而无需真正涉及事件:
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
}
}
严格来说,事件订阅可以做任何事情。您可以实现这样的事件:
private EventHandler weirdEvent;
public event EventHandler WeirdEvent
{
add { weirdEvent += value; } // Subscribe as normal
remove { weirdEvent = null; } // I'm bored with *all* the handlers
}
但通常事件只是委托给 Delegate.Combine
and Delegate.Remove
,这些方法是 +=
和 -=
在 C# 中的语法糖。
我的 article on events and delegates 包含有关组合和删除的确切情况的更多详细信息。
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);
调用点击事件会显示两次断点。
只需使用 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
这应该也是安全的。
Property_Saved += Property_Saved_Handler;
Property_Saved -= Property_Saved_Handler;
Property_Saved -= Property_Saved_Handler;
在 C# 5 中,取消订阅事件时 -= 运算符的行为是什么。
假设多次订阅同一个事件对于这个应用逻辑是有效的,例如:
Property_Saved += Property_Saved_Handler;
Property_Saved += Property_Saved_Handler;
Property_Saved += Property_Saved_Handler;
现在我们订阅了三遍。
使用以下一行代码取消订阅后:
Property_Saved -= Property_Saved_Handler;
还剩多少订阅? 2? none? ...?
之后还剩下两个。每个 -=
只删除一个订阅。至少,如果它仅使用常规委托来支持事件,情况就是如此。
您可以轻松地看到这一点,而无需真正涉及事件:
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
}
}
严格来说,事件订阅可以做任何事情。您可以实现这样的事件:
private EventHandler weirdEvent;
public event EventHandler WeirdEvent
{
add { weirdEvent += value; } // Subscribe as normal
remove { weirdEvent = null; } // I'm bored with *all* the handlers
}
但通常事件只是委托给 Delegate.Combine
and Delegate.Remove
,这些方法是 +=
和 -=
在 C# 中的语法糖。
我的 article on events and delegates 包含有关组合和删除的确切情况的更多详细信息。
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);
调用点击事件会显示两次断点。
只需使用 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
这应该也是安全的。
Property_Saved += Property_Saved_Handler;
Property_Saved -= Property_Saved_Handler;
Property_Saved -= Property_Saved_Handler;