C# 中的事件驱动类

本文关键字:事件驱动 | 更新日期: 2023-09-27 17:56:31

我正在创建一个事件驱动的类,以便当我向它传递一系列数据时,它将处理并在准备就绪时返回值。

下面是我目前正在使用以下代码的代码,但它非常讨厌,我不确定是否可以比这更简单。

   public delegate void MyEventHandler(double result);
    public static MyEventHandler EventComplete;
    public static void MakeSomethingHappen(double[] data)
    {
        ThreadPool.QueueUserWorkItem(DoSomething, data);
    }
    private static void DoSomething(object dblData)
    {
        InvokeEventComplete(AndSomethingElse((double[])dblData));
    }
    private static void InvokeEventComplete(double result)
    {
        if (EventComplete != null)
        {
            EventComplete(result);
        }
    }
    public static double AndSomethingElse(double[] data)
    {
         //do some code
         return result; //double
    }

在我的主类中,我只是将一个方法连接到事件,如下所示,

MyClass.EventComplete += new MyClass.EventCompleteHandler(MyClass_EventComplete);

C# 中的事件驱动类

你在这里:

  • 将事件公开为实际事件,而不是可公开访问的成员委托。
  • 消除了额外的委托声明,并使用了通用委托操作。
  • 消除了冗长的额外调用函数。
  • 使用 lambda 表达式进行事件注册。

编辑的代码是:

MyClass.EventComplete += (result) => Console.WriteLine("Result is: " + result);
public class MyClass
{
    public static event Action<double> EventComplete;
    public static void MakeSomethingHappen(double[] data)
    {
        ThreadPool.QueueUserWorkItem(DoSomething, data);
    }
    private static void DoSomething(object dblData)
    {
        var result = AndSomethingElse((double[])dblData);
        if (EventComplete != null)
        {
            EventComplete(result);
        }
    }
    public static double AndSomethingElse(double[] data)
    {
        //do some code
        return result; //double
    }
}

需要考虑的一些事项...

.NET 中有一个EventHandler<T> where T : EventArgs,但权衡是你最终会编写一个自定义 EventArgs 来传递双精度数据,而不是自定义委托。我仍然认为这是一个更干净的模式。

如果要将事件定义为

public static MyEventHandler EventComplete = delegate {};
//using a no-op handler like this has implications on Garbage Collection

使用无操作 lambda 表达式初始化事件会阻止 GC 吗?

您可以每次都保存if(EventComplete != null)检查,从而使调用...方法冗余。

您还可以简化

MyClass.EventComplete += new MyClass.EventCompleteHandler(MyClass_EventComplete);
to
MyClass.EventComplete += MyClass_EventComplete;

除此之外,它看起来还不错。我认为代码周围的所有static都只是来自在控制台应用程序中工作:-)

尝试使用标准事件模式(在FCL中使用数千次)

// in [CompleteEventArgs.cs] file
public class CompleteEventArgs : EventArgs {
    private readonly double _result;
    public CompleteEventArgs(double result) {
        _result = result;
    }
    public double Result {
        get { return _result; }
    }
}
// inside your class
// don't forget 'event' modifier(!) it prevents lots of illegal stuff
// like 'Complete = null' on the listener side
public static event EventHandler<CompleteEventArgs> Complete;
public static void MakeSomethingHappen(double[] data) {
    ThreadPool.QueueUserWorkItem(DoSomething, data);
}
private static void DoSomething(object dblData) {
    OnComplete(new CompleteEventArgs(AndSomethingElse((double[])dblData)));
}
// if you're working with a 'normal' (non-static) class
// here should be 'protected virtual' modifiers to allow inheritors
// use polymorphism to change the business logic
private static void OnComplete(CompleteEventArgs e) {
    if (Complete != null)
        Complete(null, e); // in 'normal' way here stands 'this' instead of 'null'
                           // this object (link to the sender) is pretty tricky
                           // and allows extra flexibility of the code on the listener side
}
public static double AndSomethingElse(double[] data) {
    double result = 0;
    //do some code
    return result; //double
}