【问题标题】:Why do we specify a delegate along with an event, why not just use an event in C#?为什么我们要指定一个委托和一个事件,为什么不在 C# 中使用一个事件?
【发布时间】:2019-07-06 23:43:21
【问题描述】:

为什么我们在事件中指定一个委托,为什么不在 C# 中使用事件呢?

例如,我有以下代码:

class Shop
{
    internal delegate void _EventHandler(object sender, GoodsInfoEventArgs e);
    internal event _EventHandler GoodsArrived;

    public void BringGoods(string goods)
    {
        if (GoodsArrived != null)
        {
            GoodsArrived(this, new GoodsInfoEventArgs(goods));
        }
    }
}

为什么那些开发过 C# 的人不通过以下方式实现事件:

class Shop
{
    internal event _EventHandler GoodsArrived;

    public void BringGoods(string goods)
    {
        if (GoodsArrived != null)
        {
            GoodsArrived(this, new GoodsInfoEventArgs(goods));
        }
    }
}

我的意思是没有代表。

我知道该事件在 C# 中是如何工作的。如果有任何订阅的代表,它只会调用所有订阅的代表,否则它将等于 null。而且我也知道事件和代表之间的区别。该事件只允许对委托进行加减,但不允许更改指针(我们可以对事件进行+=-=操作,但不能对事件进行=操作),而委托允许执行所有加法、减法和赋值操作。因此,事件是委托的包装器,并且包装器允许控制委托可以更改的方式。

话虽如此,我不明白为什么需要在程序中定义事件的每个地方都定义一个委托。

如果您不理解我的问题的一部分,请向我提问,我会提供更多信息。

谢谢。

很抱歉造成混乱。我的意思是,为什么不使用这样的东西:

internal event _EventHandler(object sender, GoodsInfoEventArgs e) GoodsArrived;

?

【问题讨论】:

  • 当你不知道它的定义(委托)时,你怎么能有一个事件。如果你订阅了一些东西,你总是需要知道参数等等。或者我不明白你的问题,因为你的第二个代码块不起作用)。
  • 我实际上并不完全理解您对第二个替代示例的意思。在那个代码 sn-p 中,_EventHandler 实际上是什么?它没有在任何地方声明,编译器应该如何处理?
  • 请注意(在此示例中)您可以简单地使用EventHandler<GoodsInfoEventArgs> 而不是声明您自己的委托(尽管GoodsInfoEventArgs 需要从EventArgs 派生)。
  • 当您不知道要提供什么参数时,您将如何触发该事件?委托描述事件处理程序方法将具有哪些参数,因此您的 fire-event-method 应提供哪些参数。
  • @HimBromBeere,为什么不在事件声明中直接指定参数?谢谢。

标签: c# events syntax delegates observer-pattern


【解决方案1】:

正如您在问题中提到的,该事件提供了订阅和取消订阅的机制。然而,委托需要定义可以处理事件的方法的签名。有一个默认签名(带有参数 sender 和 args 的 void),但您可以为 EventArgs 使用另一种类型,也可以省略 sender 参数。

此外,您还可以使用pre-defined delegateEventHandler,因此如果您坚持使用默认签名并使用EventArgs 作为参数,则不必自己创建委托。

internal event EventHandler GoodsArrived;

如果您想为事件参数提供自定义类,您可以使用generic version of the delegate

public class MyEventArgs : EventArgs 
{
  // ...
}

internal event EventHandler<MyEventArgs> GoodsArrived;

至于您的更新,如果您使用开箱即用的EventHandler 代表之一,您就快到了。你有一个标准的签名,不需要自己创建一个委托。

将事件基于委托的决定提供了很大的灵活性,您可能需要也可能不需要。您可以定义使用正确参数集的事件,也可以为多个事件重用现有委托。默认的EventHandler 实现大大简化了事情,并支持您定义符合最佳实践的事件(不带走灵活性)。

从我的观点和经验来看,直接在活动中定义签名不会增加太多。只需使用开箱即用的 EventHandler 代表即可;您可以立即识别签名,而不必自己定义委托。

【讨论】:

  • 谢谢。我稍微更新了我的问题。我不明白,为什么 C# 的开发人员会决定将delegateevent 纠缠在一起,为什么不在event 声明中直接指定event 需要知道的所有内容?这会让事情变得很清楚。 (这有点类似于构造函数与初始化函数的问题。有时开发人员会创建初始化函数,即使可以只使用构造函数。最终有人忘记在需要的地方调用初始化函数并遇到麻烦)跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-07
  • 1970-01-01
  • 1970-01-01
  • 2016-03-10
  • 1970-01-01
相关资源
最近更新 更多