2009-08-30 78 views
3

我试图让做以下的事情:将委托与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'。有没有办法做到这一点?或者我应该改变我的所有方法接受参数对象[]作为参数?

回答

4

严格否,方法签名必须完全由委托指定的签名相匹配(除对于协变匹配)。但是,您可以创建object[]阵列并输入到Delegate.DynamicInvoke(object[] args)

编辑:

如果您有关于方法的信息被调用,您可以使用MethodBase.GetParameters().Length获取参数的数目,这样你就可以正确地大小非类型化参数数组。

为标杆,不过,我想你最好使用实现必要的标杆OPS一个抽象基类:

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; 
    } 

    ///<summary>Override this method with the code to be benchmarked.</summary> 
    protected abstract void RunMethod() 
    { 
    } 
} 

虚拟方法调度具有相当的潜伏期代表,并比动态调用好得多。

+0

谢谢!)对不起,没有标记你的伟大答案。只是忘了它。我已经很久以前使用过这些代码,但只是今天标记它) – 0100110010101 2009-10-06 20:20:09

+0

感谢您接受答案。并非每个人都在意在本网站上回到“堆栈”以跟踪最新的变化。 – 2009-10-09 16:32:02

2

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

所以,是的,您需要更改所有的方法,或者使用匿名方法的包装,像这样:

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

请问使用params关键字匹配代表是否有任何方法?

他们仍然要尊重类型的差异。

params仅仅是合成糖,用于说明从那以后,调用站点的所有参数都被认为是该方法中相同数组的一部分。

因此,对于方法定义为:


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); 

因为,虽然公司3包含公司在运行时,它是稳定的抽象类型是对象。

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

现在,让我们与您的代码不工作,你的真正原因预期:类型方差

你委托的定义是:


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

和你的目标的方法:


public abstract void InsertObjects (Company c); 

当调用de使节:


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

你essentialy说你可以调用传递一个数组与任何类型的对象,而不是类型公司的目标InsertObjects。

这当然是编译器不允许的。

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


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); 
} 

然后,它会编译,因为你会被传递客户的阵列,以接受任何一种方法一种物体。

结论: 参数不影响类型变异规则。