.NET:正在创造新的EventArgs的每一个事件触发一个很好的练习时间?
-
23-09-2019 - |
题
例如,我有个基本事件发布的方法:
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的。但是似乎在.NET Framework EventArgs
的各种衍生没有被设计成是可变的,(没有制定者),这阻碍了从饲养的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);
}
编辑:固定代码示例,应当更清楚现在
解决方案
我将每次创建一个新的不可变的对象被烧制,因为有在事件参数的值。
主要的原因是,如果同时被处理现有事件的新事件再次打响了,会发生什么?
这将可能发生在多线程应用程序,但如由以下示例在单个线程甚至可能发生:
第一个事件是具有以下值烧制:
extendedArgs.someProperty1 = "Fire 1";
extendedArgs.someProperty2 = "Fire 1 Other Stuff";
然后莫名其妙的第一个事件处理程序的东西会导致事件再次以以下的参数被解雇:
extendedArgs.someProperty1 = "Fire 2";
extendedArgs.someProperty2 = "Fire 2 Other Stuff";
所有事件处理程序的第二事件进行处理,现在我们回到处理事件处理程序的其余部分中的第一事件。
现在由于相同的目的使用的所有的事件处理程序中的第一事件现在将具有“火2”作为其someProperty1,作为第二事件改写的值。
如@nobugz提到不用怕创建短命垃圾。
其他提示
首先,为什么拿一个EventArgs参数传送给烧法,如果你只是忽略它呢?那才是真正的浪费,但资源消耗比谎言,你的方法是告诉它的调用者少的问题。只需通过对这一论点,你的射击方法可能不会有访问相关信息,以创建反正EventArgs对象:
protected virtual OnSomeEvent(EventArgs e)
{
var handler = SomeEvent;
if (handler != null)
{
handler(this, e);
}
}
所以,现在我们有直的,如果你的EventArgs的对象没有任何有意义的信息告诉你的用户,只需使用EventArgs.Empty,那它是什么在那里。你可以遵循相同的模式为您定制的EventArgs类,但说实话,你担心什么。创建EventArgs的对象将永远不会在你的应用程序的瓶颈,如果是,你有设计问题。
我被你的OnExtendedEvent
代码混淆了一点 - 你的意思来重新调度的事件作为SomeEvent
当一个客户端添加一个事件处理程序,他们期望他们能够同时处理事件以除去事件处理程序,如下所示:
someObject.SomeEvent += OnSomeEvent;
// ...
private void OnSomeEvent(object sender, EventArgs e)
{
someObject.SomeEvent -= OnSomeEvent;
}
如果你不遵循标准的调度实践,该代码会抛出异常非常使用你的代码的人的意外。