如何在C#中实现类似C++的可变参数委托接收函数(无需显式转换)
在C#中实现类似C++的通用函数调用器
C#没有C++那样的可变模板参数特性,但可以通过泛型方法重载+编译器自动类型推断实现目标效果,无需显式声明Func<int, int>这类委托类型,同时保持类型安全。
实现代码
using System; public static class FunctionInvoker { // 无参数函数的调用重载 public static TResult Test<TResult>(Func<TResult> func) { return func(); } // 单参数函数的调用重载 public static TResult Test<T, TResult>(Func<T, TResult> func, T arg) { return func(arg); } // 双参数函数的调用重载 public static TResult Test<T1, T2, TResult>(Func<T1, T2, TResult> func, T1 arg1, T2 arg2) { return func(arg1, arg2); } // 三参数函数的调用重载 public static TResult Test<T1, T2, T3, TResult>(Func<T1, T2, T3, TResult> func, T1 arg1, T2 arg2, T3 arg3) { return func(arg1, arg2, arg3); } // 可根据需求继续添加更多参数的重载(最多支持16个输入参数,对应Func的最大参数数量) } public class Program { // 测试函数1:单参数,返回int static int Foo(int i) { return i + 1; } // 测试函数2:三参数,返回int static int Bar(int a, int b, int c) { return a + b + c; } // 测试函数3:无参数,返回字符串 static string Greet() { return "Hello from C#!"; } static void Main() { // 直接传入方法组和参数,编译器自动推断委托类型 Console.WriteLine(FunctionInvoker.Test(Foo, 3)); // 输出:4 Console.WriteLine(FunctionInvoker.Test(Bar, 1, 2, 3)); // 输出:6 Console.WriteLine(FunctionInvoker.Test(Greet)); // 输出:Hello from C#! } }
原理说明
- 重载覆盖参数场景:通过定义不同参数数量的
Test重载,覆盖常用的函数参数个数(0到16个,对应.NET内置Func委托的最大参数限制)。 - 自动类型推断:调用时直接传入方法组(如
Foo)和参数,C#编译器会自动将方法组隐式转换为匹配的Func委托类型,无需手动声明。 - 类型安全保障:全程保持编译期类型检查,不会像
dynamic调用那样丢失类型安全。
进阶简化(C# 11+)
如果使用C# 11及以上版本,可以利用变长泛型参数特性简化重载,无需手动编写多个重载方法:
using System; public static class FunctionInvoker { public static TResult Test<TResult, params TArgs[]>(Func<TArgs, TResult> func, TArgs args) { return func(args); } }
调用方式和之前完全一致,编译器会自动处理不同参数数量的函数。
内容的提问来源于stack exchange,提问作者racc2
相关产品推荐
相关产品推荐

