事件处理程序/引发程序代码段

本文关键字:程序 代码 事件处理 | 更新日期: 2023-09-27 17:57:46

我想听听对以下代码片段的意见。有什么可以改进的吗?事件处理程序/引发程序的命名是否遵循最佳实践?我知道在同一个类中处理和引发事件没有那么有用,但这只是一个片段。

public class MyControl
{
    public MyControl()
    {
        this.LogWritten += this.HandleMyControlLogWritten;
    }
    // Event handler
    void HandleMyControlLogWritten(object sender, EventArgs e)
    {
    }
    // Event object
    public event Action<object, EventArgs> LogWritten;
    // Event raiser
    protected virtual void OnLogWritten(EventArgs e)
    {
        if (this.LogWritten != null)
        {
            this.LogWritten(this, e);
        }
    }
}

事件处理程序/引发程序代码段

我建议的主要更改是获得事件处理程序的副本:

// Event raiser
protected virtual void OnLogWritten(EventArgs e)
{
    var handler = this.LogWritten;
    if (handler != null)
    {
        handler(this, e);
    }
}

如果您计划(最终)在多线程场景中使用此类,这一点非常重要。因此,我发现养成使用的习惯是一个很好的"最佳实践"。问题是,当在多个线程中使用时,在不创建副本的情况下,附加的唯一"处理程序"可能会在null检查和调用之间取消订阅,这将导致运行时错误。通过复制到临时变量(var handler = this.LogWritten;)行,您有效地创建了订阅者列表的"快照",然后检查其是否为null,并在需要时调用。

另一个变化是事件声明本身。代替使用Action<T1,T2>:

// Event object
public event Action<object, EventArgs> LogWritten;

我建议使用EventHandler<TEventArgs>(如果您想使用自定义EventArgs子类)或EventHandler(用于标准EventArgs)。这些是更多的"标准实践",将是其他开发人员所期望的:

// Event object
public event EventHandler LogWritten;