2013-04-03 24 views
1

我有一個通用函數CallLater應該接受任意的其他函數,並可能稍後用一些參數調用它。所有類型的功能都應該被支持 - 靜態,實例,私有,公共。藉助反射在CallLater中動態分析和構建參數。但是,在將函數傳遞給CallLater之前,其中一些可能需要綁定到固定值。如何將具有某些綁定參數的任意函數傳遞給另一個函數?

例如:

void CallLater(Delegate d) { 
    // Expects a function that returns string and has one argument of arbitrary type. 
    if (d.Method.GetParameters().Length == 1 && 
     d.Method.ReturnType == typeof(string)) { 
    object param1 = Activator.CreateInstance(d.Method.GetParameters()[0].ParameterType); 
    Console.WriteLine((string)d.DynamicInvoke(param1)); 
    } 
} 

// Has one extra float parameter. 
string MyFunc(int a, float b) { ... } 

我的想法是做這樣的事情:

float pi = 3.14f; 
CallLater(delegate(int a) { return MyFunc(a, pi); }); 

但這無法正常工作,編譯器抱怨:

Error CS1660: Cannot convert `anonymous method' to non-delegate type `System.Delegate' (CS1660) (test-delegate) 

什麼正確的方法來實現我的目標?

P.S.請不要提供解決方案來聲明一個固定的委託類型,因爲CallLater更復雜,並且可能支持可變數量的參數。

P.P.S.這可能是我的解決方案是Func,但我目前無法在Mono上使用它。

+0

'params object []'讓您使用可變數量的參數 – pascalhein

+3

在C#中搜索術語「currying」。你會發現這樣的事情:http://stackoverflow.com/questions/411572/proper-currying-in-c-sharp –

回答

1

您可以隨時重新聲明Func自己:

public delegate TReturn FFunc<TArg,TReturn>(TArg arg); 

,你可以使用正是如此:

float pi = 3.14f; 
CallLater((FFunc<int,string>)(delegate(int a) { return MyFunc(a, pi); })); 
+0

這似乎只限於一個參數。 CallLater應該能夠接受任意數量的參數。我是否需要更改CallLater的聲明或將委託參數類型工作正常嗎? –

+0

Ooooh,你真的想研究「currying」,就像別人提到的那樣;我認爲基於你正在尋找這個用例的方法中的註釋。 – JerKimball

0

我會建議使用在你打電話要執行的方法匿名函數。這些將在執行匿名方法後執行。

private static void ExecuteBoolResult(Func<bool> method) 
{ 
    bool result = method(); 
    if (!result) 
    { 
     throw new InvalidOperationException("method did not return true"); 
    } 
} 

CheckBoolResult(() => AnotherFunction("with ", 3, " parameters")); 
CheckBoolResult(() => AnotherFunction(2, "parameters")); 
相關問題