8

例如,我有一个基本事件发布方法:

    protected virtual OnSomeEvent(EventArgs e)
    {
        var handler = SomeEvent;
        if (handler != null)
        {
            handler(this, e);
            // handler(this, new EventArgs());// EDIT: Yes it should be
                                           // handler(this, e),
                                           // ignore this one :D
        }
    }

OnSomeEvent对于在触发时覆盖并引发附加事件的派生类:

    protected override OnSomeEvent(EventArgs e)
    {
        base.OnSomeEvent(e);

        if (ExtendedEvent != null)
        {
            OnExtendedEvent(e);
        }
    }

    protected void OnExtendedEvent(EventArgs e)
    {
       // some stuff done
       // new information the ExtendedEventArgs object needs 
       //  is not available until this point

       ExtendedEvent(this, new ExtendedEventArgs(someStuff, someOtherStuff));
    }

如果派生像这样继续下去,它将为需要它的每一代派生类创建一个新的派生 EventArgs。但是,似乎EventArgs.NET 框架上的各种派生并非设计为可变的(没有设置器),这不鼓励对象保留 EventArgs 的单个实例并随时修改它。

所以每次这样的事件触发时,它都会为所有涉及的EventArgs对象重新分配内存。在一个事件可以每秒触发数十次的图形密集型应用程序中(例如OnPaint控件上的事件),这真的是一个好习惯吗?

我是否应该进行一些更改OnExtendedEvent()并使其ExtendedEventArgs可变,以便可以进行以下操作?

    protected ExtendedEventArgs extendedArgs = ExtendedEventArgs.Empty;
    protected void OnExtendedEvent(EventArgs e)
    {
       // some stuff done
       // new information the ExtendedEventArgs object needs 
       //  is not available until this point

       extendedArgs.someProperty1 = someStuff;
       extendedArgs.someProperty2 = someOtherStuff;

       ExtendedEvent(this, extendedArgs);
    }

编辑:修复了示例代码,现在应该更清楚了。

4

3 回答 3

5

首先,如果您只是忽略它,为什么还要在您的触发方法中使用 EventArgs 参数呢?那是真正的浪费,但资源消耗的问题比你的方法告诉调用者的谎言要小。只需传递参数,您的触发方法可能无论如何都无法访问相关信息来创建 EventArgs 对象:

protected virtual OnSomeEvent(EventArgs e)
{
    var handler = SomeEvent;
    if (handler != null)
    {
        handler(this, e);
    }
}

所以,既然我们已经直截了当,如果您的 EventArgs 对象没有有意义的信息告诉您的订阅者,只需使用 EventArgs.Empty,这就是它的用途。您可以为自定义 EventArgs 类遵循相同的模式,但老实说,您无需担心任何事情。创建 EventArgs 对象永远不会成为您的应用程序的瓶颈,如果是,您就会遇到设计问题。

于 2010-01-29T00:31:06.320 回答
3

每次触发它时,我都会创建一个新的不可变对象,因为事件参数中有值。

主要原因是如果在处理现有事件时再次触发新事件会发生什么?

这可能会发生在多线程应用程序中,但甚至可能发生在单个线程上,如下例所示:

使用以下值触发第一个事件:

extendedArgs.someProperty1 = "Fire 1";
extendedArgs.someProperty2 = "Fire 1 Other Stuff";

然后不知何故,第一个事件处理程序做了一些事情,导致事件再次被以下参数触发:

extendedArgs.someProperty1 = "Fire 2";
extendedArgs.someProperty2 = "Fire 2 Other Stuff";

所有的事件处理程序都是为第二个事件处理的,现在我们回到处理第一个事件的其余事件处理程序。

现在,由于使用了相同的对象,第一个事件的所有事件处理程序现在都将“Fire 2”作为它们的 someProperty1,因为第二个事件覆盖了这些值。

正如@nobugz 提到的,不要害怕制造短暂的垃圾。

于 2010-01-29T03:10:31.717 回答
1

我对您的OnExtendedEvent代码感到有些困惑-您的意思是将事件重新分配为SomeEvent?

当客户端添加事件处理程序时,他们希望能够在处理事件时删除事件处理程序,如下所示:

someObject.SomeEvent += OnSomeEvent;
// ...
private void OnSomeEvent(object sender, EventArgs e)
{
    someObject.SomeEvent -= OnSomeEvent;
}

如果你不遵循标准的调度实践,这段代码会抛出一个异常,让使用你的代码的人大吃一惊。

于 2010-01-29T00:21:26.630 回答