问题描述
我确信我只是不了解有关 C# 中事件和/或委托的基本知识,但为什么我不能在此代码示例中进行布尔测试:
I am sure that I am just not understanding something fundamental about events and/or delegates in C#, but why can't I do the Boolean tests in this code sample:
public class UseSomeEventBase {
public delegate void SomeEventHandler(object sender, EventArgs e);
public event SomeEventHandler SomeEvent;
protected void OnSomeEvent(EventArgs e) {
// CANONICAL WAY TO TEST EVENT. OF COURSE, THIS WORKS.
if (SomeEvent != null) SomeEvent(this, e);
}
}
public class UseSomeEvent : UseSomeEventBase {
public bool IsSomeEventHandlerNull() {
// "LEFT HAND SIDE" COMPILER ERROR
return SomeEvent == null;
}
}
class Program {
static void Main(string[] args) {
var useSomeEvent = new UseSomeEvent();
useSomeEvent.SomeEvent +=new UseSomeEventBase.SomeEventHandler(FuncToHandle);
// "LEFT HAND SIDE" COMPILER ERROR
if (useSomeEvent.SomeEvent == null) {
}
var useSomeEventBase = new UseSomeEventBase();
useSomeEventBase.SomeEvent += new UseSomeEventBase.SomeEventHandler(FuncToHandle);
// "LEFT HAND SIDE" COMPILER ERROR
if (useSomeEventBase.SomeEvent == null) {
}
}
static void FuncToHandle(object sender, EventArgs e) { }
}
推荐答案
事件实际上只是一个添加"操作和一个删除"操作.您无法获取该值,您无法设置该值,您无法调用它 - 您可以订阅事件的处理程序 (add
) 或取消订阅 (remove代码>).这很好——它是封装,简单明了.发布者可以适当地实施添加/删除,但除非发布者选择提供详细信息,否则订阅者无法修改或访问特定于实施的部分.
An event is really just an "add" operation and a "remove" operation. You can't get the value, you can't set the value, you can't call it - you can just subscribe a handler for the event (add
) or unsubscribe one (remove
). This is fine - it's encapsulation, plain and simple. It's up to the publisher to implement add/remove appropriately, but unless the publisher chooses to make the details available, subscribers can't modify or access the implementation-specific parts.
C# 中的类字段事件(您没有指定添加/删除位)隐藏了这一点 - 它们创建了一个委托类型的变量和一个事件.事件的添加/删除实现只是使用变量来跟踪订阅者.
Field-like events in C# (where you don't specify the add/remove bits) hide this - they create a variable of a delegate type and an event. The event's add/remove implementations just use the variable to keep track of the subscribers.
在类内部您引用变量(因此您可以获取当前订阅的委托,执行它们等),在类外部您引用事件本身(因此只有添加/删除功能).
Inside the class you refer to the variable (so you can get the currently subscribed delegates, execute them etc) and outside the class you refer to the event itself (so only have add/remove abilities).
类字段事件的替代方法是您自己显式实现添加/删除,例如
The alternative to field-like events is where you explicitly implement the add/remove yourself, e.g.
private EventHandler clickHandler; // Normal private field
public event EventHandler Click
{
add
{
Console.WriteLine("New subscriber");
clickHandler += value;
}
remove
{
Console.WriteLine("Lost a subscriber");
clickHandler -= value;
}
}
有关详细信息,请参阅我关于事件的文章.
See my article on events for more information.
当然,事件发布者可以提供更多信息——你可以写一个像ClickHandlers
这样的属性来返回当前的多播委托,或者HasClickHandlers
返回是否有.不过,这不是核心事件模型的一部分.
Of course the event publisher can also make more information available - you could write a property like ClickHandlers
to return the current multi-cast delegate, or HasClickHandlers
to return whether there are any or not. That's not part of the core event model though.
这篇关于在 C# 中,为什么我不能测试事件处理程序在它定义的类之外的任何地方是否为空?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!