我正在尝试编写一个函数,它将另一个函数作为参数(稍后调用)我知道如果我知道signature of the function beforehand它是可行的,但这是否可能,如果我不这样做? (比如在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)
答案 0 :(得分:2)
如果您对该功能一无所知,则需要使用Reflection(并支付性能损失)。
让它接受Delegate
,然后致电.DynamicInvoke()
。
答案 1 :(得分:1)
void DelayedCall<T>(Action<T> functionToCallLater,
float delayInSecs, params T[] values)
{
//here do something like (just as an example)
functionToCallLater(values);
}
你有对象[]作为你的值,但我假设你想要使用泛型来指定它们的类型。此外,由于您调用的方法看起来不像返回类型,因此我使用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);
这将删除方法需要处理的一些方案和功能。通过减少方法签名需要处理的可能选项,问题变得更简单,更易于管理。
答案 2 :(得分:0)
我认为这在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 ""; }