C
C#2w ago
yeon

Creating a method that takes a generic method and its variadic parameters as arguments and call it i

I need a way to pass generic static methods and its argument to another method, and the static method inside this another method. In C++, I can easily achieve this with variadic templates and std::forward:
#include <utility>
#include <cstdio>

template <typename Func, typename... Args>
void actual_call_func(Func func, Args &&...args) {
func(std::forward<Args>(args)...);
}

int main() {
auto func = std::printf;
constexpr const char* param_0 = "%d + %d = %d";
int param_1 = 3;
int param_2 = 4;
int param_3 = 3 + 4;

actual_call_func(func, param_0, param_1, param_2, param_3);
}
#include <utility>
#include <cstdio>

template <typename Func, typename... Args>
void actual_call_func(Func func, Args &&...args) {
func(std::forward<Args>(args)...);
}

int main() {
auto func = std::printf;
constexpr const char* param_0 = "%d + %d = %d";
int param_1 = 3;
int param_2 = 4;
int param_3 = 3 + 4;

actual_call_func(func, param_0, param_1, param_2, param_3);
}
But I don't know how to do this easily in C#; Previously I just captured all the required arguments into a lambda, which calls the static method inside of it, and passed it as an single Action.
// Let's just pass this to the actual call function
Action call = () => { Console.WriteLine(param0, param1); };
// Let's just pass this to the actual call function
Action call = () => { Console.WriteLine(param0, param1); };
But this breaks when I have non-capturable arguments such as Span<T>. And I don't want to use params object[]? to box the arguments. The only way I can think of is declaring the ActualCallFunc one by one:
void ActualCallFunc(Action func);
void ActualCallFunc<T>(Action<T> func, T param0);
void ActualCallFunc<T0, T1>(Action<T0, T1> func, T0 param0, T1 param1);
void ActualCallFunc<T0, T1, T2>(Action<T0, T1, T2> func, T0 param0, T1 param1, T2 param2);
...
void ActualCallFunc(Action func);
void ActualCallFunc<T>(Action<T> func, T param0);
void ActualCallFunc<T0, T1>(Action<T0, T1> func, T0 param0, T1 param1);
void ActualCallFunc<T0, T1, T2>(Action<T0, T1, T2> func, T0 param0, T1 param1, T2 param2);
...
But not only this is cumbersome, it would not work if sometimes the parameter needs to use ref. Is there any nice way to solve this like in C++?
9 Replies
Angius
Angius2w ago
C# has no variadic generic parameters There is a source generator I see, written by @WhiteBlackGoose: https://github.com/WhiteBlackGoose/InductiveVariadics A proposal has been made in 2015: https://github.com/dotnet/roslyn/issues/5058
yeon
yeonOP2w ago
Hmm, too bad it is not a thing. Source generator approach looks interesting, but I think it's a bit overkill solution for my usecase Hmm, I'll just declare these manually for now then
Angius
Angius2w ago
You could do some fucky-wucky stuff with delegates, if you really must
MODiX
MODiX2w ago
Angius
sharplab.io (click here)
void Call(Delegate d, object data) {
d.DynamicInvoke(data);
}
Call((string s) => Console.Write(s), "hello");
void Call(Delegate d, object data) {
d.DynamicInvoke(data);
}
Call((string s) => Console.Write(s), "hello");
Try the /sharplab command! | React with ❌ to remove this embed.
yeon
yeonOP2w ago
Hmm, I believe this DynamicInvoke also boxes the parameters, I would like to avoid that if possible Thanks for suggesting, anyways
Anton
Anton2w ago
put your parameters in a struct this kind of pattern in C# is a burden to maintain
WhiteBlackGoose
did it pop up on your search engine?
Angius
Angius2w ago
ya
WhiteBlackGoose
cool 😄

Did you find this page helpful?