【问题标题】:c# - Passing anonymous functions instead of hooking up eventsc# - 传递匿名函数而不是连接事件
【发布时间】:2026-01-06 08:20:02
【问题描述】:

我最近发现了 Actions 和匿名函数的用法,以及它们在处理任务时如何方便。我已经做了几个测试,将匿名函数传递给一个类以类似于事件。

我正在做的一个例子是......

var myForm = new MyForm();
myForm.OnCertainEvent(output => {
    //interact with UI based on feedback.
}));

然后在表单本身中,我将设置一个 Action 属性,并将 Action 传递给 OnCertainEvent 方法。

我认为这种语法非常简洁,而不是声明事件、委托并将它们与+= 语法挂钩。

这是不好的做法吗?显然它不是传统的,但它有任何负面影响吗?本质上我只是提供一个回调。

【问题讨论】:

  • 如果你只需要一个回调,那么是的,没关系。
  • 从“可能的问题”的角度来看,这并不是一个非常糟糕的做法。最后,它转换回以任何一种方式调用委托。我能看到的唯一问题是您可能会做出一些可能的线程安全疏忽、简化或遗漏,并且它们可能会在以后对您不利。不过,可能不是。另一方面,重新发明*并以非标准方式做事通常被认为是不好的做法。如果您需要类似事件的功能,为什么不直接使用事件呢?
  • 您在此处提供的是“单播”委托。也就是说,您提供了一个在发生某些事情时调用的委托(适合一个动作)。能够支持多个委托会非常有用,这些委托被称为“多播”委托。 msdn.microsoft.com/en-us/library/… 如果您可以在添加或删除委托时调用代码,那就太好了msdn.microsoft.com/en-us/library/bb882534.aspx 事件就是这样诞生的。
  • 您的问题与传递匿名函数而不是连接事件毫无共同之处。您可以传递普通函数(也称为方法指针)以及使用匿名 lambda 连接事件。

标签: c# events anonymous-function


【解决方案1】:

这是不好的做法吗?

这是一个非常间接的问题。这实际上取决于几个关键因素,例如:

  • 您想在想要使用ActionAction<T> 委托的地方做什么?
  • 您是否为实际处理事件的类正确地取消连接事件处理程序?
  • 您是否指导将ActionAction<T> 委托回调作为事件处理程序?

您似乎正在尝试将回调分配为事件处理程序,但您实现它的方式似乎不正确。似乎您正试图通过一个名为OnCertainEvent 的方法注册您的回调,缺陷是消费者可能会多次调用它,并且基本上您最终会得到与调用的回调数量相同的执行次数——这有意义吗?

事件是多播的,这意味着您可以连接无限数量的处理程序,作为对单个 event 的回调进行侦听。这是我所说的一个例子,我写了一个快速的.NET Fiddle。这种编写方式永远无法取消订阅听众,因为他们是匿名的,这可能会导致问题。

明明不是传统的,但有什么负面影响吗?

只要您了解后果并正确清理代码,就应该没问题。在您想要处理此类事件的情况下,您可以通过使用类的构造函数(在您的特定情况下为MyForm)更安全地执行此操作。这是另一个 .NET Fiddle 来证明这一点。

这是完全可能的并且超级强大,在我看来现在被认为是“传统的”。创建自己的delegate 实现的概念已经消失,自从引入泛型和lambda expressions 以来就一直存在。最后一个链接是一个无耻的插件,我希望所有这些都有意义并回答您的问题!

【讨论】:

  • 这是完美的。第一个 .NET Fiddle 就是我的想法。感谢您的宝贵时间。
【解决方案2】:

自 C# 中的 lambdas 以来,这是一种非常常用的模式,但有它的优点和不便。

不便之处在于只有一个“接收者”可以成为目标,通过一个事件,您可以根据需要连接任意数量的接收者。

优点,很容易编写一个即发即弃的类型表达式,而不是挂钩到事件。

如果您想探索更多关于如何相互通信不同类的构造,请查看委托模式,而不是 .net 委托,而是公开可能调用的函数的接口,就像在 Java 中所做的那样。

【讨论】:

    【解决方案3】:

    不,这样做完全没问题。你想观察自己,不过我会将传递的方法限制为几行。真的,这取决于你想在方法中做什么。如果您正在做的事情与主要方法抽象地分开,那么实际上将其作为一个独立的方法可能会更好。如果只是简单的更改或更新之类的,我认为内联代码会更优雅。

    请谨慎使用方法范围之外的本地数据。这是合法的,但如果您遇到问题,很有可能就是问题所在。

    【讨论】: