2009-08-30 37 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); 
} 

然後,它會編譯,因爲你會被傳遞客戶的陣列,以接受任何一種方法一種物體。

結論: 參數不影響類型變異規則。