我将尝试澄清我的问题:
我有一个名为 Draw 的函数(有人(XNA)每秒调用她 60 次),我有很多对象要绘制,所以我有以下代码: void Draw() { obj1.draw(); obj2.draw(); obj3.draw(); ....}
如果我将创建一个由 Draw() 引发的事件,并且所有对象都将注册该事件,是否会对性能产生影响?
如果我不清楚我要问的是:通过注册事件来调用函数与常规调用不同吗?
关于性能,我认为Jon Skeet 的例子非常有说服力,代表不会给性能增加任何显着的开销,甚至可能会改善它。
对于事件/委托,您需要考虑的一个因素是处理监听事件的解除挂钩对象,否则您的引用计数将无法正确重置,并且您会发现自己存在内存泄漏。避免使用匿名方法,除非您准备存储对它们的引用,以便它们可以在 Dispose 等上不连线。
ildasm 显示函数的直接调用是使用“call method”命令执行的,而通过事件调用是使用“callvirt delegatename::Invoke()”执行的。看起来直接调用应该更快,但让我们考虑一下什么是 Invoke()。Invoke 不是 Delegate 或 MulticastDelegate 类的成员。这是编译器生成的特殊方法
.method public hidebysig virtual instance void
Invoke(string s) runtime managed
{
}
此方法不包含任何实现,这可能看起来很奇怪。但是如果我们注意“运行时”规范,魔法就会消散。“运行时”意味着代码将在运行时生成,而且我们知道,它只会发生一次。所以理论上两者在生产力方面应该是相同的。
至于 Jon Skeet 的测试,我多次启动它并在委托的帮助下将直接呼叫与呼叫互换,并没有得到委托提高性能的确认。有时代表赢了,有时直接打电话赢了。我认为这是因为 GC 或 .NET 中的其他东西影响了测试,或者只是通过 Windows 切换进程。