接下来的问题- 使用C#将方法作为参数传递,以及我的一些个人经验,我想了解更多有关调用委托的性能而不是仅使用C#调用方法的性能。
尽管委托非常方便,但我有一个应用程序通过委托进行了许多回调,当我们重写该程序以使用回调接口时,速度得到了改善。这是.NET 2.0的版本,所以我不确定3和4的变化。
如何在编译器/ CLR中内部处理对委托的调用,这如何影响方法调用的性能?
编辑 -为了澄清我的意思是委托与回调接口。
对于异步调用,我的类可以提供OnComplete事件和调用者可以预订的关联委托。
或者,我可以用调用者实现的OnComplete方法创建一个ICallback接口,然后向该类注册自己,该类将在完成时调用该方法(即Java处理这些事情的方式)。
我还没有看到这种效果-我当然从来没有遇到过瓶颈。
这是一个非常粗糙的基准,它(无论如何在我的盒子上)显示了委托实际上比接口要 快 :
using System; using System.Diagnostics; interface IFoo { int Foo(int x); } class Program : IFoo { const int Iterations = 1000000000; public int Foo(int x) { return x * 3; } static void Main(string[] args) { int x = 3; IFoo ifoo = new Program(); Func<int, int> del = ifoo.Foo; // Make sure everything's JITted: ifoo.Foo(3); del(3); Stopwatch sw = Stopwatch.StartNew(); for (int i = 0; i < Iterations; i++) { x = ifoo.Foo(x); } sw.Stop(); Console.WriteLine("Interface: {0}", sw.ElapsedMilliseconds); x = 3; sw = Stopwatch.StartNew(); for (int i = 0; i < Iterations; i++) { x = del(x); } sw.Stop(); Console.WriteLine("Delegate: {0}", sw.ElapsedMilliseconds); } }
结果(.NET 3.5; .NET 4.0b2大致相同):
Interface: 5068 Delegate: 4404
现在我没有特别的信念,这意味着委托 确实 比接口要快…但是这让我相当确信,委托不会比接口慢一个数量级。此外,这在委托/接口方法中几乎不执行任何操作。显然,随着每次调用越来越多的工作,调用成本将变得越来越少。
要注意的一件事是,您不会多次创建新的委托,而只使用一个接口实例。这 可能 会引起问题,因为它会引发垃圾回收等。如果您在循环内使用实例方法作为委托,则发现在循环外声明委托变量,创建单个委托实例并重用会更有效。它。例如:
Func<int, int> del = myInstance.MyMethod; for (int i = 0; i < 100000; i++) { MethodTakingFunc(del); }
效率比:
for (int i = 0; i < 100000; i++) { MethodTakingFunc(myInstance.MyMethod); }
难道这就是您所看到的问题?