委托与params关键字匹配任何方法?

我正在努力完成以下事情:

public delegate void SomeMethod(params object[] parameters); 

那是我的代表。 我有一些方法将运行此SomeMethod委托(无论传递什么)并返回执行的时间跨度。

  public TimeSpan BenchmarkMethod(SomeMethod someMethod, params object[] parameters) { DateTime benchmarkStart = DateTime.Now; someMethod(parameters); DateTime benchmarkFinish = DateTime.Now; return benchmarkFinish - benchmarkStart; } 

我也有一些方法:

 public abstract void InsertObjects (Company c); 

所以,我宣布:

 SomeMethod dlg = new SomeMethod(InsertObjects); TimeSpan executionTime = BenchmarkMethod(dlg, c); 

但它没有运行,说’InsertObjects’没有重载匹配委托’TestFactory.MeasuringFactory.SomeMethod’。 有没有办法做到这一点?或者我应该改变我的所有方法来接受params对象[]作为参数?

严格来说,方法签名必须与委托指定的签名完全匹配(协变匹配除外)。 但是,您可以创建一个object[]数组并将其提供给Delegate.DynamicInvoke(object[] args)

编辑:

如果您有关于要调用的方法的信息,可以使用MethodBase.GetParameters().Length来获取参数的数量,这样您就可以正确调整无类型参数数组的大小。

但是,对于基准测试,我认为您最好使用实现必要的基准测试操作的抽象基类:

 abstract class Benchmark { TimeSpan Run() { Stopwatch swatch = Stopwatch.StartNew(); // Optionally loop this several times and divide elapsed time by loops: RunMethod(); swatch.Stop(); return swatch.Elapsed; } ///Override this method with the code to be benchmarked. protected abstract void RunMethod() { } } 

虚拟方法调度具有与委托相当的延迟,并且比动态调用更好。

委托与params关键字匹配任何方法?

不, 他们仍然需要尊重类型差异。

params只是合成糖,因为说从那时起,呼叫站点的所有参数都被认为是该方法上同一arrays的一部分。

因此,对于定义为的方法:

 TimeSpan BenchmarkMethod(SomeMethod someMethod, params Company[] parameters) 

你可以做:

 Company company1 = null; Company company2 = null; //In BenchmarkMethod, company1 and company2 are considered to be part of //parameter 'parameters', an array of Company; BenchmarkMethod(dlg, company1, company2); 

但不是:

 Company company1 = null; object company3 = new Company(); BenchmarkMethod(dlg, company1, company3); 

因为,虽然company3在运行时包含公司,但它的静态类型是对象。

所以现在我们知道params只是在方法上定义一个数组,它允许你在调用站点使用更方便的语法。

现在让我们继续说明您的代码无法按预期工作的真正原因:键入方差

您的代理人定义为:

 public delegate void SomeMethod(params object[] parameters); 

并将方法定位为:

 public abstract void InsertObjects (Company c); 

调用委托时:

 SomeMethod dlg = new SomeMethod(InsertObjects); TimeSpan executionTime = BenchmarkMethod(dlg, c); 

您实际上是在说可以调用InsertObjects向它传递一个包含任何类型对象的数组,而不是类型为Company的对象。

当然,编译器不允许这样做。

相反,如果您反转委托的类型和目标方法,例如:

 public delegate void SomeMethod(params Company[] parameters); public TimeSpan BenchmarkMethod(SomeMethod someMethod, params Company[] parameters) { DateTime benchmarkStart = DateTime.Now; someMethod(parameters); DateTime benchmarkFinish = DateTime.Now; return benchmarkFinish - benchmarkStart; } public void InsertObjects(object c) { Console.WriteLine(c); } 

然后它将编译,因为您将把一个Customer数组传递给一个接受任何类型对象的方法。

结论: params不影响类型方差规则。

匹配params参数是编译器魔术,并且代理人不存在这样的魔法。 它将匹配一个方法,该方法在正确的位置具有兼容类型的数组,但没有别的。

所以,是的,您需要更改所有方法,或使用匿名方法作为包装器,如下所示:

 SomeMethod dlg = new SomeMethod(delegate(Object[] parameters) { InsertObjects((Company)parameters[0]); };