Dan*_*an7 8 c# events event-handling eventargs
例如,我有一个基本事件发布方法:
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
}
}
Run Code Online (Sandbox Code Playgroud)
对于派生类,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));
}
Run Code Online (Sandbox Code Playgroud)
如果派生继续这样,它将为需要它的每一代派生类创建一个新的派生EventArgs.然而,似乎EventArgs.NET框架上的各种派生不是设计为可变的(没有setter),这阻止了一个对象保留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);
}
Run Code Online (Sandbox Code Playgroud)
编辑:修复了示例代码,现在应该更清楚了.
首先,如果你只是忽略它,为什么要把一个EventArgs参数带到你的射击方法?这是真正的浪费,但资源消耗比你的方法告诉其呼叫者的谎言更少问题.只需传递参数,您的触发方法可能无法获得相关信息,无论如何都可以创建EventArgs对象:
protected virtual OnSomeEvent(EventArgs e)
{
var handler = SomeEvent;
if (handler != null)
{
handler(this, e);
}
}
Run Code Online (Sandbox Code Playgroud)
所以,既然我们已经直截了当,如果您的EventArgs对象没有有意义的信息告诉您的订阅者,那么只需使用EventArgs.Empty,就是它的用途.您可以为自定义的EventArgs类遵循相同的模式,但老实说,您不必担心任何事情.创建EventArgs对象永远不会成为应用程序的瓶颈,如果是,则存在设计问题.
每次触发时我都会创建一个新的不可变对象,因为事件参数中有值。
主要原因是如果在处理现有事件时再次触发新事件会发生什么?
这可能会发生在多线程应用程序中,但甚至可能发生在单线程上,如下例所示:
第一个事件使用以下值触发:
extendedArgs.someProperty1 = "Fire 1";
extendedArgs.someProperty2 = "Fire 1 Other Stuff";
Run Code Online (Sandbox Code Playgroud)
然后,第一个事件处理程序以某种方式执行某些操作,导致使用以下参数再次触发事件:
extendedArgs.someProperty1 = "Fire 2";
extendedArgs.someProperty2 = "Fire 2 Other Stuff";
Run Code Online (Sandbox Code Playgroud)
第二个事件的所有事件处理程序都已处理完毕,现在我们返回处理第一个事件的其余事件处理程序。
现在,由于使用了相同的对象,第一个事件的所有事件处理程序现在都将“Fire 2”作为其 someProperty1,因为第二个事件覆盖了这些值。
正如 @nobugz 提到的,不要害怕创建短暂的垃圾。