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

如何实现支持任意数量泛型参数的C# JSGridVM类?

实现支持任意多不同类型JSTable的JSGridVM方案

先直接回答你的第一个问题:C#里的Func<>系列委托确实是靠多组泛型参数重载实现的。它并没有什么“黑科技”支持无限制泛型参数,只是预定义了从0个输入参数到16个输入参数的重载版本,覆盖绝大多数常见场景。

回到你的核心需求:要让JSGridVM能容纳任意数量、任意RowType的JSTable<RowType>实例。其实你不需要把所有RowType都塞进JSGridVM的泛型参数里(而且C#本身也不支持可变数量的泛型参数),换个思路就能轻松解决。


最优解决方案:非泛型接口+非泛型JSGridVM

这个方案简单、类型安全,还能完美满足你“任意数量JSTable”的需求:

1. 定义非泛型接口IJSTable

先创建一个非泛型接口,用来统一所有JSTable<RowType>的公共非泛型成员:

public interface IJSTable
{
    bool AllowEditingRows { get; set; }
    bool AllowDeletingRows { get; set; }
    string UpdateURL { get; set; }
    string DeleteURL { get; set; }
    List<JSGridColumn> Columns { get; set; }
}

2. 让JSTable<RowType>实现这个接口

修改你的JSTable类,继承IJSTable:

public class JSTable<RowType> : IJSTable
{
    public JSTable() { }

    public JSTable(List<RowType> rows, List<JSGridColumn> columns, bool allowEditingRows, bool allowDeletingRows, string updateURL, string deleteURL)
    {
        Rows = rows;
        Columns = columns;
        AllowEditingRows = allowEditingRows;
        AllowDeletingRows = allowDeletingRows;
        UpdateURL = updateURL;
        DeleteURL = deleteURL;
    }

    public List<RowType> Rows { get; set; }
    public List<JSGridColumn> Columns { get; set; }
    public bool AllowEditingRows { get; set; }
    public bool AllowDeletingRows { get; set; }
    public string UpdateURL { get; set; }
    public string DeleteURL { get; set; }
}

3. 实现JSGridVM

现在JSGridVM不需要任何泛型参数,直接持有List<IJSTable>,还可以加个便捷的AddTable方法:

public class JSGridVM
{
    public List<IJSTable> Tables { get; set; } = new List<IJSTable>();

    // 便捷方法,自动推导RowType
    public void AddTable<RowType>(JSTable<RowType> table)
    {
        Tables.Add(table);
    }
}

使用示例

这样你想加多少个不同类型的JSTable都可以:

// 创建不同RowType的表格
var userTable = new JSTable<User>(userRows, userColumns, true, true, "/api/users/update", "/api/users/delete");
var orderTable = new JSTable<Order>(orderRows, orderColumns, false, true, "/api/orders/update", "/api/orders/delete");
var productTable = new JSTable<Product>(productRows, productColumns, true, false, "/api/products/update", "/api/products/delete");

// 初始化JSGridVM并添加所有表格
var jsGridVM = new JSGridVM();
jsGridVM.AddTable(userTable);
jsGridVM.AddTable(orderTable);
jsGridVM.AddTable(productTable);

如果你非要JSGridVM<SomeClass1, SomeClass2>的声明方式

如果确实想接近你期望的泛型声明语法,只能像Func<>那样预定义重载,但这本质上还是有限制的,而且对你的场景来说没什么实际价值。举个例子:

// 基础非泛型类
public class JSGridVM
{
    public List<IJSTable> Tables { get; set; } = new List<IJSTable>();
}

// 支持1个泛型参数的版本
public class JSGridVM<T1> : JSGridVM
{
    public void AddTable(JSTable<T1> table) => Tables.Add(table);
}

// 支持2个泛型参数的版本
public class JSGridVM<T1, T2> : JSGridVM<T1>
{
    public new void AddTable(JSTable<T2> table) => Tables.Add(table);
}

// 继续扩展到T3、T4……最多到你愿意写的数量

但这种方式需要你预先写好所有可能的泛型参数数量的重载,和Func<>一样最多覆盖有限数量,而且JSGridVM本身并不需要知道这些RowType的具体类型,所以完全没必要这么做。


总结一下

  • Func<>确实是靠多组泛型参数重载实现的,没有真正的“无限制”泛型参数;
  • 对你的场景来说,非泛型接口+非泛型JSGridVM是最优解,简单、灵活,能容纳任意数量的不同类型JSTable;
  • 泛型声明的方式只是语法糖,无法实现真正的无限制,反而增加不必要的复杂度。

内容的提问来源于stack exchange,提问作者Tyler Youngs

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:02:52