[英]Will Delegate with params keyword match any method?
我正在努力完成以下事情:
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;
}
///<summary>Override this method with the code to be benchmarked.</summary>
protected abstract void RunMethod()
{
}
}
虛擬方法調度具有與委托相當的延遲,並且比動態調用更好。
委托與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);
因為,雖然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]);
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.