委托方法里有一个 DynamicInvoke 的方法,可以在不清楚委托实际类型的情况下执行委托方法,但是用 DynamicInvoke 去执行的话会比直接用 Invoke 的方法会慢上很多,差了两个数量级,所以在知道委托类型的情况下尽可能使用 Invoke 执行,但有时候我们并不知道委托的实际类型。

优化方法,直接执行委托的对应的方法,DynamicInvoke 实际也是调用的对应的方法,我们如果执行调用对应的方法就可以优化

  1. delegate func = (Func<string, string>)str=> "12345";
  2. string paramString = "321";
  3. // Invoke
  4. ((Func<string, string>)func).Invoke(paramString);
  5. // DynamicInvoke
  6. func.DynamicInvoke(new object[]{ paramString });
  7. // Method Invoke
  8. func.Method.Invoke(func.Target, new object[]{ paramString });

下面做一个性能测试,测试代码如下:

  1. public class DelegateInvokeTest
  2. {
  3. private readonly Delegate _func, _func1;
  4. private readonly string parameter;
  5. private readonly int paramInt;
  6. public DelegateInvokeTest()
  7. {
  8. parameter = "Test";
  9. paramInt = 1;
  10. _func = (Func<string, string>)(str => str);
  11. _func1 = (Func<int, int>)(val => 0);
  12. }
  13. [Benchmark(Baseline = true)]
  14. public object Invoke()
  15. {
  16. return ((Func<string, string>)_func).Invoke(parameter);
  17. }
  18. [Benchmark]
  19. public object InvokeBoxing()
  20. {
  21. return ((Func<int, int>)_func1).Invoke(paramInt);
  22. }
  23. [Benchmark]
  24. public object DynamicInvoke()
  25. {
  26. return _func.DynamicInvoke(parameter);
  27. }
  28. [Benchmark]
  29. public object DynamicInvokeBoxing()
  30. {
  31. return _func1.DynamicInvoke(paramInt);
  32. }
  33. [Benchmark]
  34. public object MethodInfoInvoke()
  35. {
  36. return _func.Method?.Invoke(_func.Target, new object[] { parameter });
  37. }
  38. [Benchmark]
  39. public object MethodInfoInvokeBoxing()
  40. {
  41. return _func1.Method?.Invoke(_func1.Target, new object[] { paramInt });
  42. }
  43. [Benchmark]
  44. public object ReflectInvoke()
  45. {
  46. var funcType = typeof(Func<,>).MakeGenericType(typeof(string), typeof(string));
  47. var method = funcType.GetProperty("Method")?.GetValueGetter()?.Invoke(_func) as MethodInfo;
  48. var target = funcType.GetProperty("Target")?.GetValueGetter()?.Invoke(_func);
  49. return method?.Invoke(target, new object[] { parameter });
  50. }
  51. [Benchmark]
  52. public object ReflectInvokeBoxing()
  53. {
  54. var funcType = typeof(Func<,>).MakeGenericType(typeof(string), typeof(int));
  55. var method = funcType.GetProperty("Method")?.GetValueGetter()?.Invoke(_func1) as MethodInfo;
  56. var target = funcType.GetProperty("Target")?.GetValueGetter()?.Invoke(_func1);
  57. return method?.Invoke(target, new object[] { paramInt });
  58. }
  59. }

测试结果如下:

  1. BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19041.173 (2004/?/20H1)
  2. Intel Core i5-6300U CPU 2.40GHz (Skylake), 1 CPU, 4 logical and 2 physical cores
  3. .NET Core SDK=3.1.201
  4. [Host] : .NET Core 3.1.3 (CoreCLR 4.700.20.11803, CoreFX 4.700.20.12001), X64 RyuJIT
  5. DefaultJob : .NET Core 3.1.3 (CoreCLR 4.700.20.11803, CoreFX 4.700.20.12001), X64 RyuJIT

| Method | Mean | Error | StdDev | Ratio | RatioSD |

|———————– |———–

版权声明:本文为weihanli原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/weihanli/p/12732737.html