[英]Passing a generic method as a parameter in C#
我正在嘗試編寫一個函數,該函數將另一個函數作為參數(並在以后調用),如果我事先知道該函數的簽名,我知道它是可行的,但是如果我不知道,這是可能的嗎? (例如,將函數作為參數傳遞給JavaScript)
例如:
// this should accept a function with any kind of signature and return value
void DelayedCall(?? functionToCallLater, float delayInSecs, params object[] values)
{
//here do something like (just as an example)
functionToCallLater.Invoke(values);
}
編輯:我不想承擔有關functionToCallLater
任何事情,例如,它們可能看起來像這樣:
int MyFunc()
void MyFunc2()
void MyFunc3(int someParam)
string MyFunc4(int someParam, MyClass someOtherParam)
void MyFunc5<T>(params T[] values)
如果您對該功能一無所知,則需要使用Reflection(並支付性能損失)。
使它接受Delegate
,然后調用.DynamicInvoke()
。
你是這個意思嗎 :
void DelayedCall<T>(Action<T> functionToCallLater,
float delayInSecs, params T[] values)
{
//here do something like (just as an example)
functionToCallLater(values);
}
您有object []作為值,但是我假設您也想使用泛型來指定它們的類型。 另外,由於看起來好像您要調用的方法沒有返回類型,所以我使用Action<T>
代替Func<T>
。
根據以下評論,
如果要接受不同的簽名,則實際上有2個不同的選項。 像SLaks所說的第一個是使用反射。 但是,這可能變得非常復雜,因為您將不得不確定functionToCallLater中參數的位置和類型,並將其與父函數的傳入參數對齊。 有很多語義確實使這一點變得困難(盡管有可能),並且使問題普遍化以處理大量案例時,確實帶來了更多的麻煩。
處理此場景的第二種且更可驗證的方法(盡管不一定要減少工作量)是為有問題的方法創建重載:
void DelayedCall<T>(Func<T> functionToCallLater,
float delayInSecs, params T[] values)
void DelayedCall<T,R>(Func<T,R> functionToCallLater,
float delayInSecs, params T[] values)
void DelayedCall<T>(Func<T,X,R> functionToCallLater,
float delayInSecs, params T[] values)
etc.
根據重載方法的復雜程度,這可能有點乏味甚至幾乎不可能,但是它可以工作。 在這種情況下,您想問自己的真正問題是:“這是處理這種方法的最佳方法嗎?” 例如,如果在調用方法中不需要返回值,那么為什么要完全允許一個值? 您可以始終強制調用者將函數包裝在另一個遵循方法簽名的方法中,如下所示:
void DelayedCall<T>(Action<T> functionToCallLater,
float delayInSecs, params T[] values)
....
DelayledCallAction<int>(
(i) => MyMethodWhichReturnsSomething(i),
floadDelayInSecs, 1,2,3);
這消除了該方法需要處理的一些方案和功能。 通過減少方法簽名需要處理的可能選項,問題將變得更簡單,更易於管理。
我認為這在C#中可能是冗長的:/
這是一個可以接受返回或不返回值並接受0-2參數的函數的解決方案:
// signature: void MyFunc()
void DelayedCall(Action sdf, float delayInSecs)
{
}
// signature: SomeClass MyFunc()
void DelayedCall<T>(Func<T> sdf, float delayInSecs)
{
}
// signature: void MyFunc(SomeClass param1)
void DelayedCall<T>(Action<T> sdf, float delayInSecs, T values)
{
}
// signature: SomeClass MyFunc(SomeClass param1)
void DelayedCall<T, K>(Func<T, K> sdf, float delayInSecs, T values)
{
}
// signature: void MyFunc(SomeClass param1, SomeClass2 param2)
void DelayedCall<T, K>(Action<T, K> sdf, float delayInSecs, T values, K values2)
{
}
// signature: SomeClass MyFunc(SomeClass param1, SomeClass2 param2)
void DelayedCall<T, K, L>(Func<T, K, L> sdf, float delayInSecs, T values, K values2)
{
}
例如,它們接受以下內容:
void MyFunc1() { }
int MyFunc2() { return 6; }
void MyFunc3(int someParam) { }
string MyFunc4(string someParam) { return ""; }
void MyFunc5(int someParam, string someparam2) { }
string MyFunc6(string someParam, int someparam2) { return ""; }
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.