【问题标题】:Event vs EventHandler事件与事件处理程序
【发布时间】:2017-10-19 07:18:20
【问题描述】:

看了很多资料还是没看懂,谁能解释一下?

我知道什么:

声明一个事件:

public event MyEvent myEvent;

对比

声明事件处理程序:

public EventHandler MyEventHandler;

虽然 EventHandler 是 .NET 中的关键字:

public delegate void EventHandler (Send object, EventArgs e);

那么,EventHandler 是一个委托而不是一个事件,因为它没有在关键字“事件”中使用?

什么时候应该使用“Event”,什么时候应该使用“EventHandler”?

【问题讨论】:

  • event 是引发事件的事物,某些事物将订阅该事件。 EventHandler 是处理事件的东西 - 即它指定用于订阅事件的方法。
  • 一个事件有一个类型,它描述了事件引发时应该传递哪些参数以及事件处理程序必须要与事件兼容的参数类型是由委托声明描述。 EventHandler 就是这样一种声明(不是关键字),由框架提供。它规定事件处理程序必须有 2 个参数,每个人都将它们命名为 sender 和 e。 MyEvent 是另一个,由你提供,我们看不到。使用框架声明是个好主意,它使您的代码易于阅读。
  • 你越来越近了。您声明了一个简单的事件,仅此而已。不是代表,那个来自框架。事件的行为很像属性。您使用属性来限制对私有字段的访问,外部代码必须使用 get 和 set 访问器。事件类似地限制对私有委托对象的访问,外部代码只能添加和删除事件处理程序。外部代码不能引发事件,不能强制委托对象为空,也不能取消订阅由其他代码注册的处理程序。限制访问是一件好事。
  • “虽然 EventHandler 是 .NET 中的关键字:” - 不,它不是。在您的代码中,MyEventEventHandler 都是委托类型,MyEventHandler 是委托实例。

标签: c# events eventhandler


【解决方案1】:

啊,事件与代表的问题。我记得我也有这个问题...

因此,假设您正在创建一个名为“Cat”的课程,并且您希望让人们知道您的猫何时饿了。您可以通过以下两种方式之一做到这一点:在 Cat 类上公开委托或公开事件。

您可以将委托视为指向函数(或方法)的指针。因此,假设有一个名为“Person”的类有一个名为FeedCat(Cat cat) 的方法。

委托方式


如果你的猫暴露了一个名为HungryDelegate的委托,这个人可以将这个委托指向他们的FeedCat方法,这样当猫饿的时候,它就有办法在这个人身上调用FeedCat方法.

这里的问题是,只有一个人可以喂猫。假设您希望多个人能够喂猫。人们可能忙于做其他事情,因此猫能够告诉多个人它饿了是很重要的。这样一来,人们就会收到通知,并且可以在有机会时检查猫,看看是否有人已经喂过猫,如果没有,就喂它。

救援事件:


事件基本上是代表(某种类型)的列表。如果您在“Cat”类上公开Hungry 事件,则多人可以将指针(委托)添加到他们的FeedCat 方法中。

如果他们愿意,他们还可以删除指向其FeedCat 方法的指针(委托)。假设一个人搬出去了,他们的姐姐现在正在照顾猫。该人可以从猫中删除他们自己的 FeedCat 函数的委托,这样他们就不会再收到该死猫饿了的通知。

事件与多播委托?


从技术上讲,为了能够提供多个委托,您可以使用所谓的 MultiCastDelegates 来代替事件。他们是复合委托(一个链表或委托)。问题是,每个人都可以从外面惹他们。一个邪恶的人可以移除其他所有人的“FeedCat”代表,而这只可怜的猫会饿死(或者必须学会打猎)。

使用事件时重要的是,该人无法看到添加到事件中的其他人的代表,也无法删除它们或与它们进行交互(原则上)。 p>

【讨论】:

  • 监听者 = 代表,观察者 = 事件
【解决方案2】:

暴露一个(public字段

 public EventHandler MyEventHandler;

是一种不好的做法:一个小错字很容易破坏代码:

 MyClass demo = new MyClass();

 demo.MyEventHandler += MyMethod;

 ...

 // Can you see the error? = instead of correct += ?
 // MyMethod will not be called since this assignment 
 demo.MyEventHandler = MyReaction;  

这就是为什么你应该使用专门为此设计的事件

 public event EventHandler MyEventHandler;

如果我们尝试之前的demo,我们会得到编译时错误

 MyClass demo = new MyClass();

 ...

 demo.MyEventHandler = MyReaction; // <- doesn't compile, insist on +=

在极少数情况下,您可能需要明确的基于委托的字段,但这些字段应该被隐藏,例如 private,而不是 public

// We don't expose the field
private EventHandler m_MyEventHandler;

// ... But event:
public event EventHandler MyEventHandler {
  add {
    //TODO: extra logic on += operation

    m_MyEventHandler += value;
  }
  remove {
    //TODO: extra logic on -= operation

    m_MyEventHandler -= value;
  }  
} 

【讨论】:

  • 第三个代码片段(在“这就是为什么你应该使用专门为此设计的event”之后)应该是public event EventHandler MyEventHandler;,即应该添加event关键字(否则它与第一个代码片段相同)。
【解决方案3】:

代表、事件(事件处理程序/事件侦听器)、概念(多播/广播)、动作和功能

这将是一个很长但最简单的解释,这个话题如此令人讨厌的问题是因为人们只是用不同的词来解释同一件事

首先,你应该知道一些事情

DELEGATES:它只是一个方法列表,为什么要创建一个列表?因为当你的代码被执行时,这个列表会被一个一个地执行,只要不要听教科书的定义就可以了,你会没事的

也叫:

  • 指向函数的指针
  • 方法的包装器,可以像变量一样发送和接收方法

去创建一个委托

[[access modifier] delegate [return type] [delegate name]([parameters])]

example: public delegate int demo(int a);

现在要执行存储在一个名为委托的列表中的所有这些方法,你去

1. demo.invoke(a);
2. demo(a);   ..... both are valid

在使用 beginInvoke 的异步编程中使用点并明确表示调用会大放异彩,但这超出了本主题的范围

还有一件事叫做“创建委托/实例化委托的对象”,这听起来很像,但只是为了避免混淆(对于上面的例子)

example : demo del = new demo(); (or) Public demo del = null;

要将任何方法添加到称为委托的列表中,您可以 += 并且您还需要在“满足方法的要求”后将其删除 -=

(满足方法的要求意味着您不再需要该方法处于活动状态或也称为“监听”)如果您不删除它,它可能会导致“内存泄漏”,这意味着您的计算机内存将被活着吃掉, 技术上分配的内存不会被释放

例子:说有一个方法

public int calculate (int c)

to add this method to delegate you go

1.  del = calculate;
2.  del += calculate; .... all are valid

to remove 

del -= calculate

首先注意委托和方法之间的相似之处,返回类型(输出)和输入/参数是相同的,这是一个规则,你不能在委托中添加任何随机或一堆方法它需要遵循输入输出规则

现在为什么有两种不同的方式来做一件事,唯一不同的是赋值运算符(+,=),这就引入了一个新的话题,叫做

活动

这不过是一个受约束的委托版本,它仍然是一个方法列表,当人们解释这些术语时不会混淆,他们会更改名称,所以坚持这个理解

什么是约束?你不能这样做del = calculate; 它有什么害处,比如说一堆方法被添加到委托(列表)中,你这样做?所有的都被消灭了,只剩下一个方法“计算”,所以为了防止使用事件, 事件语法

公共事件演示 del = null;

您不能对事件做的另一件事是直接调用委托,如 demo.invoke,因为它是公共的,它可以被访问和调用,但对于事件,它不能

现在您只需将方法添加到事件(一种特殊类型的委托)

何时使用事件与委托,取决于您的情况,但实际上事件很受欢迎

几个关键词

MULTICASTING:向委托添加多个方法 广播:向事件添加多个方法

PUBLISHER:执行方法的那个(广播中使用的术语),只有一个实体 SUBSCRIBER:正在执行的方法,可以是多个

LISTENER:与订阅者相同,但该术语用于多播

事件处理程序:与订阅者/事件侦听器相同,那么有什么区别?基本上是一样的,有人说事件监听器检测到事件的发生,事件处理程序“处理”或执行代码,实际上是一样的!

action 和 func 只是已经创建和实例化的委托,所以一句话就两行代码,区别仅在于返回类型

ACTION:在接受 0 或多于 1 个输入时不返回任何内容

FUNC:返回一件事并接受参数

如果你不擅长阅读这里是关于这个主题的最佳视频

https://www.youtube.com/playlist?list=PLFt_AvWsXl0dliMtpZC8Qd_ru26785Ih_

【讨论】:

    猜你喜欢
    • 2018-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多