C#中声明适配有无参数的泛型委托并添加至Dictionary的问题
解决C#中用单一泛型委托适配有参/无参方法并存入字典的问题
看起来你想要用一个泛型委托同时适配「带同类型输入输出」和「无参数返回值」的方法,然后把这些委托实例存入Dictionary<string, Delegate>中。下面给你两种可行的方案,兼顾简洁性和灵活性:
方案1:给自定义泛型委托添加可选参数
通过给泛型委托的参数设置默认值,让它同时兼容无参数和带同类型参数的方法:
public class BOMock : BOBase { // 带可选参数的泛型委托,同时支持有参/无参场景 public delegate T Del<T>(T item = default); public int Id { get; set; } public string Name { get; set; } private Dictionary<string, Delegate> BODictionary = new Dictionary<string, Delegate>(); public BOMock() { // 存入无参数返回int的方法 BODictionary.Add("GetId", new Del<int>(GetId)); // 存入带int参数返回int的方法 BODictionary.Add("SetId", new Del<int>(SetId)); // 存入无参数返回string的方法 BODictionary.Add("GetName", new Del<string>(GetName)); // 存入带string参数返回string的方法 BODictionary.Add("SetName", new Del<string>(SetName)); } // 无参数方法示例 private int GetId() => Id; private string GetName() => Name; // 带参数方法示例 private int SetId(int id) { Id = id; return id; } private string SetName(string name) { Name = name; return name; } }
调用字典中的委托
建议转换回具体的泛型委托类型再调用(避免性能较差的DynamicInvoke):
// 调用无参数的GetId if (BODictionary.TryGetValue("GetId", out var del) && del is Del<int> getIdDel) { int result = getIdDel(); // 无需传参,因为参数是可选的 Console.WriteLine(result); } // 调用带参数的SetId if (BODictionary.TryGetValue("SetId", out var setDel) && setDel is Del<int> setIdDel) { int result = setIdDel(123); Console.WriteLine(result); }
方案2:复用.NET内置的Func委托(更简洁)
如果你不想自定义委托,可以直接用.NET原生的Func系列泛型委托,它天生支持多种签名:
Func<TResult>:无参数,返回TResultFunc<T, TResult>:输入T,返回TResult(可让T和TResult类型一致)
代码会更精简:
public class BOMock : BOBase { public int Id { get; set; } public string Name { get; set; } private Dictionary<string, Delegate> BODictionary = new Dictionary<string, Delegate>(); public BOMock() { BODictionary.Add("GetId", new Func<int>(GetId)); BODictionary.Add("SetId", new Func<int, int>(SetId)); BODictionary.Add("GetName", new Func<string>(GetName)); BODictionary.Add("SetName", new Func<string, string>(SetName)); } private int GetId() => Id; private string GetName() => Name; private int SetId(int id) { Id = id; return id; } private string SetName(string name) { Name = name; return name; } }
调用方式和方案1类似,转换回对应的Func类型即可:
if (BODictionary.TryGetValue("GetName", out var del) && del is Func<string> getNameFunc) { Console.WriteLine(getNameFunc()); }
重要注意事项
- 尽量避免使用
Delegate.DynamicInvoke(),它是反射调用,性能差且无编译时类型检查,转换回具体委托类型调用是更优选择。 - 如果你的方法需要支持「输入输出类型不同」的场景,方案2的
Func委托会更灵活,因为它支持任意数量的输入参数和不同的返回值类型。
内容的提问来源于stack exchange,提问作者user3580768
相关产品推荐
相关产品推荐

