正确实现 EventArgs Empty

Implementing EventArgs Empty Correctly

我正在尝试正确理解 EventsEventArgs,但无法完全掌握 EventArgs.Empty 属性.

EventArgs 实现:

public static readonly EventArgs Empty;

并允许我们创建一个 EventHandler 并使用以下方式调用它:

public event EventHandler<EventArgs> TestHappening;

private void MyMethod()
{
    TestHappening( this, EventArgs.Empty );
}

现在我已经研究了一些基于 EventArgs and none of them seem to implement this so I'm flying a little blind even though I've read all the documentation I could find regarding EventArgs.Empty 的 classes。根据文档,"The value of Empty is a read-only instance of EventArgs equivalent to the result of calling the EventArgs constructor"。

基于此,我创建了以下实现:

public class TestEventArgs : EventArgs
{
    public static readonly TestEventArgs Empty;

    public bool UpdatedValue { get; private set; }

    TestEventArgs()
        : this( false )
    {
    }

    public TestEventArgs( bool updatedValue )
    {
        this.UpdatedValue = updatedValue;
    }
}

public event EventHandler<TestEventArgs> TestHappening;

private void MyMethod()
{
    TestHappening( this, EventArgs.Empty );
}

TestEventArgs.Empty 的使用是在实例化一个 class 还是它到底在做什么?

此外,尽管我检查的所有子classes 都没有使用 Empty,但它们仍然可用,不可用的 [=47= 是不是很混乱? ] 暴露了?

最后,根据我研究的各种文档,实际实例化 EventArgs 的时间有两个主要差异。哪个被认为是 "more" 正确的?:

OnTestHappening( new TestEventArgs( false ) );

private void OnTestHappening( TestEventArgs e )
{
    var handler = TestHappening;

    if ( handler != null )
        handler( this, e );
}

OnTestHappening( true );

private void OnTestHappening( bool foo )
{
    var handler = TestHappening;

    if ( handler != null )
        handler( this, new TestEventArgs( foo ) );
}

如果你真的需要Empty字段,你应该自己考虑。如果您不使用它,则不应创建它。 EventArgs class 没有任何变量或属性,因此每次都创建一个新实例没有意义。在你的情况下,因为你有一个默认值,所以有两个 'empty' TestEventArgs,一个用于 true 和一个用于 false 确实更有意义(如果你真的想要并且它在您的场景中有意义)。

您在实施过程中还遗漏了一些其他要点,我已在下面修复这些问题:

public class TestEventArgs : EventArgs
{
    public static readonly TestEventArgs True = new TestEventArgs(true);

    public static readonly TestEventArgs False = new TestEventArgs(false);

    public bool UpdatedValue { get; private set; }

    public TestEventArgs(bool updatedValue)
    {
        this.UpdatedValue = updatedValue;
    }

    public event EventHandler<TestEventArgs> TestHappening;

    private void MyMethod()
    {
        EventHandler<TestEventArgs> eh = TestHappening;

        eh?.Invoke(this, TestEventArgs.True);
    }
}

我改变了什么:

  1. Empty 实例化为 new TestEventArgs,因为那也是 EventArgs.Empty 的定义。
  2. 我已经实现了事件处理程序的线程安全版本(您的代码中的第二个示例)。如果订阅事件的事件处理程序列表发生变化,则您的第一个示例不安全。你的第二个是,因此你应该选择那个。

关于你的最后一点:这取决于你是否打算让调用委托更改对象(它是传递一个实例还是传递多个实例)。在您的情况下,由于无法更改实例,所以没关系。