【问题标题】:C# has to subscribe to an event before event calledC# 必须在事件调用之前订阅事件
【发布时间】:2017-06-16 01:16:44
【问题描述】:

我想实现一个快速的方法来给一个事件添加监听器,我的实现:

public class AccountManager 
{

    public delegate void CheckIfLoggedInListener(EventArgs e);
    public event CheckIfLoggedInListener SetCheckIfLoggedInListener;

    public void CheckIfLoggedIn()
    {                
         if(SetCheckIfLoggedInListener!=null)
             SetCheckIfLoggedInListener(new EventArgs("e"));
    }
}

现在,我必须先设置监听器,然后调用方法,如果其他开发者不注意,很容易搞砸:

//this will not work, because you invoke the event before subscribing
accountManager.CheckIfLoggedIn();
accountManager.SetCheckIfLoggedInListener += (e) => { Debug.Log(e.param); };

我想知道是否有办法使订单不是强制性的?

【问题讨论】:

  • 这就是 事件的工作方式。这个想法是只触发事件如果有东西要触发。
  • 如果未附加事件侦听器,那么您希望代码如何工作?如果尚未附加,您是否希望代码生成侦听器?如果必须按照开发人员的意愿进行编程,则根本不需要异常处理。你不应该写糟糕的代码,因为开发者不想关注。
  • 如果您担心其他人无法正确使用事件,请不要这样做。如果他们有任何好处,他们会正确订阅您的活动。此外,您想要的行为可能是有害的。如果在事件被调用后向事件添加监听器是有意怎么办?如果不应该在第一次调用方法时调用侦听器,而应该在每个后续方法调用时调用侦听器怎么办?作为库开发人员,试图“解决”此类种潜在错误是浪费时间,甚至会伤害那些真正知道自己在做什么的人。
  • 顺便说一句,您的代码在任何情况下都可能无法正常工作。首先分配给本地,然后检查是否为空。 var evt = SetCheckIfLoggedInListener; if(evt!=null) evt(new EventArgs("e"));
  • @cineammispelt 或者,在较新版本的 .NET 中,您可以使用更好的 SetCheckIfLoggedInListener?.Invoke(new EventArgs("e"));。 VS2015(可能还有旧版本)实际上会建议将旧的事件调度模式重构到这个替代版本中。

标签: c#


【解决方案1】:

您可以获取泛型委托的参数,该参数将是Action<T> 类型的对象,在您的情况下,您的方法中将是Action<EventArgs>,以确保:

编辑:

你需要调整它才能工作,而不是Action<EventArgs>,我们必须使用Action<Object,EventArgs>this post explains why is that

public void CheckIfLoggedIn(Action<object,EventArgs> action)
{
    SetCheckIfLoggedInListener = action.Invoke;

     if(SetCheckIfLoggedInListener!=null)
         SetCheckIfLoggedInListener(null,new EventArgs());
}

打电话时你需要这样做:

//this will not work, because you invoke the event before subscribing
accountManager.CheckIfLoggedIn((o,e) => { Console.WriteLine("event fired");  });

Working DEMO Fiddle here

通过这种方式,您可以强制用户注册要在触发事件时调用的实现。

希望对你有帮助!

【讨论】:

  • 这看起来正是我要找的东西!因为我想将这两行合并为一行。我会试试这个!
  • 所以我什至可以在函数末尾添加 this.SetCheckIfLoggedInListener -= action 来防止内存泄漏,对吧?
  • 我收到错误消息,“无法将类型 'System.Action 隐式转换为 'CheckIfLoggedInListener'”,你知道为什么吗?
  • 我已经用可编译代码更新了帖子,并参考了为什么我们需要这样做。
猜你喜欢
  • 1970-01-01
  • 2020-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多