Java 或 C# 中的事件/委托

2022-01-15 00:00:00 delegates event-handling c# java

我一直在尝试了解事件/代表,但对两者之间的关系感到困惑.我知道委托允许您调用不同的函数,而无需知道正在调用的特定函数.(例如:一个绘图函数需要接受不同函数的输入).

I've been trying to learn about events/delegates, but am confused about the relationship between the two. I know that delegates allow you to invoke different functions without needing to know what particular function is being invoked. (eg: a graphing function needs to accept inputs that are different functions to be graphed).

但我看不到事件中如何使用委托.

But I don't see how delegates are used in Events.

有人可以构建一个简单的示例(在伪代码、C# 或 Java 中)来说明与事件相关的委托的工作原理吗?

Can someone construct a simple example (in pseudocode or C# or Java) that illustrates the workings of Delegates as related to Events?

谢谢!

推荐答案

(这都是从 C# 的角度来看的.)

(This is all from a C# perspective.)

我有一篇关于事件和委托之间区别的文章.这更详细地涵盖了下面提到的所有内容.

I have an article about the differences between events and delegates. That covers everything mentioned below in a lot more detail.

基本上,我喜欢将事件视为一个属性——它是一对方法,仅此而已.一个事件不是 get/set,而是 add/remove——意思是添加这个事件处理程序"和删除这个事件处理程序".从本质上讲,这就是一个事件.

Basically I like to think of an event as being like a property - it's a pair of methods, that's all. Instead of get/set, an event has add/remove - meaning "add this event handler" and "remove this event handler". At the core, that's all an event is.

C# 也有 field-like events 这是一个快捷方式:

C# also has field-like events which are a shortcut:

 public event EventHandler Foo;

声明一个字段和一个事件,几乎是微不足道的添加/删除实现.在类中,引用 Foo 是指字段.在类之外,引用 Foo 是指事件.

declares both a field and an event, with a nearly trivial add/remove implementation. Within the class, referring to Foo refers to the field. Outside the class, referring to Foo refers to the event.

基本思想是事件允许其他代码订阅和取消订阅,方法是传入一个委托(事件处理程序).通常,订阅是通过创建一个新的多播委托来实现的,该委托包含上一个事件处理程序列表和新的.因此,如果您将事件处理程序存储在名为 myEventHandlers 的字段中,订阅实现可能是:

The basic idea is that an event allows other code to subscribe to and unsubscribe from it, by passing in a delegate (the event handler). Usually, subscription is implemented by creating a new multicast delegate containing the previous list of event handlers and the new one. So if you're storing the event handlers in a field called myEventHandlers, the subscription implementation might be:

myEventHandlers += value;

类似地取消订阅通常涉及创建一个新的多播委托没有指定的处理程序:

Similarly unsubscription usually involves creating a new multicast delegate without the specified handler:

myEventHandlers -= value;

然后,当您想要引发/触发事件时,您只需调用该多播委托 - 通常使用无效检查以避免在没有人订阅时引发异常:

Then when you want to raise/fire the event, you just call that multicast delegate - usually with a nullity check to avoid an exception being thrown if no-one has subscribed:

EventHandler handler = myEventHandlers;
if (handler != null)
{
    // You could pass in a different "sender" and "args" of course
    handler(this, EventArgs.Empty);
}

使用事件,订阅者彼此不了解,并且不能自己引发事件(通常).换句话说,它是一种封装模式,在语言和平台中都被赋予了地位.

Using events, the subscribers don't know about each other, and can't raise the event themselves (usually). In other words, it's a pattern of encapsulation, which has been given status within both the language and the platform.

相关文章