2014-10-18 50 views
4

我是一名程序員,我很懶。目前我正在使用C#中的一些OpenAL包裝器。每次我調用OpenAL方法時,我都必須使用GetError來從OpenAL請求錯誤,如果有錯誤,我會拋出異常。直到我添加了一個包含以下功能的靜態幫助類才花了很長時間:常規方法Action/Func的擴展方法

public static void Check() 
    { 
     ALError error; 
     if ((error = AL.GetError()) != ALError.NoError) 
      throw new InvalidOperationException(AL.GetErrorString(error)); 
    } 

這個工作了一段時間,但我想要更多。因此,一段時間後,我想出了以下方法:

public static void Call(Action function) 
    { 
     function(); 
     ALHelper.Check(); 
    } 

    public static void Call<TParameter>(Action<TParameter> function, TParameter parameter) 
    { 
     function(parameter); 
     ALHelper.Check(); 
    } 

    public static TReturn Eval<TReturn>(Func<TReturn> function) 
    { 
     var val = function(); 
     ALHelper.Check(); 
     return val; 
    } 

    public static TReturn Eval<TParameter, TReturn>(Func<TParameter, TReturn> function, TParameter parameter) 
    { 
     var val = function(parameter); 
     ALHelper.Check(); 
     return val; 
    } 

這個工作很大,但我還是不開心時的代碼究竟如何看,所以我決定把它一步:我將上述方法轉換爲擴展方法。因爲我知道我可以通過ActionFunc參數的方法,所以我認爲它可以用於擴展方法,將醜陋的handles = ALHelper.Eval(AL.GenBuffers, amount)變成更優雅的handles = AL.GenBuffers.Eval(amount)

不幸的是,一旦我開始使用它,我受到了一個例外的歡迎:Expression表示一個method group', where a變量,'value' or'類型'是預期的。

有點傷心,這不起作用,我真的很好奇,爲什麼這不起作用。究竟是什麼原因,您可以通過方法ActionFunc,但使用擴展方法不起作用?這是我正在使用的單聲道編譯器(.NET 4.0)的限制嗎,還是有其他內容?

回答

1

當您編寫handles = ALHelper.Eval(AL.GenBuffers, amount)時,AL.GenBuffers不是任何類型的代表。重載解決方案會考慮所有重載ALHelper.Eval,並確切找到表達式AL.GenBuffers可以轉換的一個委託類型。

當你寫handles = AL.GenBuffers.Eval(amount)AL.GenBuffers依然沒有任何類型的委託,所以AL.GenBuffers.Eval不匹配任何方法和重載解析無法幫助找到最佳匹配。

原則上,您可以編寫new Func<T, TResult>(AL.GenBuffers).Eval(...)擴展方法可以處理委託類型,但這比您已有的要糟糕。

這不是特定於單聲道。

我會做的是創建一個類(比如說MyAL),併爲所有AL的函數提供包裝。呼叫者然後可以說handles = MyAL.GenBuffers(amount);

+0

非常感謝。我已經預料到與此類似的東西,但很高興看到詳細解釋。我確實已經考慮爲AL創建自己的包裝類,它可能會幫助很多事情,但現在我會堅持將該函數作爲參數傳遞。 – Tom 2014-10-18 13:05:32

2

我想你誤解了擴展方法的概念。它們用於擴展類型。在這種情況下,AL.GenBuffers是一種方法,它不是FuncAction.它的簽名可能與它們兼容,但並不意味着它是一種func或動作或任何其他類型的委託類型。在您的示例中,由於method group conversions,您可以將其傳遞爲AL.GenBuffers。當編譯器看到方法簽名是兼容的時,它將它轉換爲delegate類型。