【问题标题】:array of events in C#?C# 中的事件数组?
【发布时间】:2009-06-12 14:49:17
【问题描述】:

基本上:

public delegate void RecvCommandHandler (ChatApplication sender, byte[] content);
event RecvCommandHandler[] commands = new RecvCommandHandler[255];

我想为每个命令号激活不同的方法/功能,但我真的不确定语法。我该怎么做?

我想我会选择一组代表来解决这个问题,但这个问题仍然很有趣。

【问题讨论】:

  • 你不能使用一个事件(或委托)和一个 eventArgs 指定做什么?
  • 除非我想要一个冗长的 switch-case 代码而没有检查 null 的选项。

标签: c# arrays events


【解决方案1】:

您可以创建一个具有运算符重载的类数组来模拟您感兴趣的行为...

public delegate void EventDelegate(EventData kEvent);

public class EventElement
{
    protected event EventDelegate eventdelegate;

    public void Dispatch(EventData kEvent)
    {
        if (eventdelegate != null)
        {
            eventdelegate(kEvent);
        }
    }

    public static EventElement operator +(EventElement kElement, EventDelegate kDelegate)
    {
        kElement.eventdelegate += kDelegate;
        return kElement;
    }

    public static EventElement operator -(EventElement kElement, EventDelegate kDelegate)
    {
        kElement.eventdelegate -= kDelegate;
        return kElement;
    }
}

public EventElement[] commands = new EventElement[255];

commands[100] += OnWhatever;
commands[100].Dispatch(new EventData());
commands[100] -= OnWhatever;

【讨论】:

    【解决方案2】:

    实际上没有事件数组的概念——这就像谈论属性数组一样。事件实际上只是让您订阅和取消订阅处理程序的方法。如果你需要能够通过索引来做到这一点,我建议你只有一对方法。 (AddCommandHandler(int, RecvCommandHandler)RemoveCommandHandler(int, RecvCommandHandler))。当然,这不支持正常的事件处理语法糖,但我认为没有很多替代方案。

    【讨论】:

    • 只是对介绍的备注——我对 Action[] 没有任何问题。所以可能有方法数组,问题在于 C# 中的事件表现得像某种方法和对象的混合。它应该是具有取消/注册方法和调用的普通类。
    • 如果我们有这样的东西会很整洁。如果我想订阅/取消订阅类似退出钩子的东西,它需要一堆事件(一些取决于执行上下文:IIS、WPF 应用程序、控制台程序。可以在不预先知道它们的情况下注入其中的一个数组/IEnumerable图书馆。
    【解决方案3】:

    另一种选择是在委托原型中指定和索引,并有一个事件处理程序“委托”给其他人,例如:

    public delegate void RecvCommandHandler (int id, ChatApplication sender, byte[] content);
    
    // ...
    
    private RecvCommandHandler[] internalhandlers;
    
    public void MyCommandHandler(int id, ChatApplication sender, byte[] content)
    {
        internalHandlers[id](id, sender, content);
    }
    

    【讨论】:

      【解决方案4】:

      我只是在寻找相同的答案,但是我的类也是 WPF 的事件发送者,所以它应该看起来与普通的 C#/WPF 事件发送者类一样多。所以我简单地添加了这个:

      致发件人:

      • 带有属性名称的枚举——这是因为缺少 nameof 而蹩脚的解决方法
      • 另一种记录请求的方法

      收件人:

      • 给定枚举的请求事件

      代码,发件人:

          public enum Properties
          {
              NetworkFileName,
              DatasetFileName,
              LearningWatch
          }
      
          private string network_filename;
          public string NetworkFileName 
          {
              get { return network_filename; }
              private set 
              {
                  if (network_filename != value)
                  {
                      network_filename = value;
                      OnPropertyChanged(Properties.NetworkFileName.ToString());
                  }
              }
          }
      
          public event PropertyChangedEventHandler PropertyChanged;
      
          protected void OnPropertyChanged(string name)
          {
              if (PropertyChanged != null)
              {
                  PropertyChanged(this, new PropertyChangedEventArgs(name));
              }
          }
      
          public void OnChange(Properties prop, Action<object, PropertyChangedEventArgs> action)
          {
              PropertyChanged += new PropertyChangedEventHandler((obj, args) => { if (args.PropertyName == prop.ToString()) action(obj, args); });
          }
      

      对于接收者:

          private void OnNetworkLoaded(object sender, PropertyChangedEventArgs e)
          {
              SetTitle();
          }
      
              ...
              ExpManager.OnChange(ExperimentManager.Properties.DatasetFileName, OnDatasetLoaded);
      

      它仍然很丑,但至少:

      • 我不必在接收器中处理“ifs”
      • 我可以轻松创建多个事件处理程序
      • 与WPF兼容
      • 没有魔法弦(我讨厌那些)

      缺点:

      • 混淆破坏了这一点(但我有专门针对这种情况的课程,这个项目只适合我,所以这里没问题)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-12-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多