You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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>:无参数,返回TResult
  • Func<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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:40:59