订阅事件有什么问题吗
MyPopup.CustomPopupPlacementCallback = popupFixCentered;
而不是:
MyPopup.CustomPopupPlacementCallback += popupFixCentered;
例如,如果我要从另一种方法更改为不同的回调,我想确保我只订阅了一个回调,而无需 -= 正确的回调。
最佳答案
嗯,看来你没有尝试过。如果这样做,您将收到以下编译错误:
The event 'XXX' can only appear on the left hand side of += or -= (except when used from within the type 'YourClass')
错误非常明显:您只能在事件上使用 +=
和 -=
运算符。
如果您尝试从定义事件的类中分配给事件
,那么它将“起作用”。但在这种情况下它似乎能够分配给事件
的原因是因为它实际上没有访问该事件。它正在访问一个自动生成的私有(private)委托(delegate)实例,您可能没有意识到该实例实际上存在。
引用自Chris Burrows' article关于主题:
outside of the class or struct that defines a field-like event E, binding to the name E resolves to the event itself, on which the only legal operation is calling an accessor; inside the class or struct that defines a field-like event E, binding to the name E resolves to the private delegate field.
要理解这一点,您需要在定义事件时将其可视化,例如:
public event EventHandler MyEvent;
...你没有看到的是,它实际上被翻译成这样的东西(我从 Jon Skeet's article on events and delegates 复制这个。另请注意,它被翻译成的确切代码在C# 版本,所以可能有点不同,但总体思路是相同的):
private EventHandler _myEvent;
public event EventHandler MyEvent
{
add
{
lock (this)
{
_myEvent += value;
}
}
remove
{
lock (this)
{
_myEvent -= value;
}
}
}
因此,当您从类的外部访问MyEvent
时,您只能调用add
和通过
方法。+=
和 -=
运算符删除
但是从在类中,访问MyEvent
意味着不同的事情。它实际上成为对您看不到的私有(private) _myEvent
委托(delegate)变量的引用,但它确实存在。因为这是委托(delegate)类型,所以您可以对其使用赋值 (=
) 运算符。
因此,为了实现您想要的目的,您可以在定义事件的同一类中定义一个公共(public)方法,并使用该方法来设置新的事件处理程序。
类似这样的事情:
public class MyClass
{
public event EventHandler MyEvent;
public void setSingleEventHandler(EventHandler eventHandler)
{
this.MyEvent = eventHandler;
}
}
但是如果您打算这样做,那么它就违背了 event
类型的目的。如果您只想在任何给定时间最多调用一个事件处理程序,那么以这种方式定义它(不使用 event
关键字)更有意义:
public class MyClass
{
public EventHandler MyEvent { get; set; }
}
引用文献
乔恩·斯基特文章:Delegates and Events
Chris Burrows 文章:(另请查看该系列的其余部分):Events get a little overhaul in C# 4, Part II: Semantic Changes and +=/-=
关于c# - 使用 = 而不是 += 订阅事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31226717/