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

如何将不同泛型实现的Worksheet实例存入同一枚举集合?

解决方案

问题的核心是C#泛型默认不支持协变转换,因此Worksheet<WorksheetItem1>无法直接转为Worksheet<IWorksheetItem>。以下是两种可行的实现方案:


方案一:定义非泛型基接口

创建一个非泛型的IWorksheet接口,封装你在GetSpreadSheet中需要访问的公共成员,让泛型Worksheet<T>实现该接口,以此统一所有Worksheet实例的类型。

代码实现

// 非泛型接口,统一公共操作
public interface IWorksheet
{
    string Name { get; set; }
    Type ItemType { get; }
    // 可选:若需要以非泛型形式访问Items,添加此属性
    IEnumerable<IWorksheetItem> Items { get; }
}

// 修改泛型Worksheet类实现IWorksheet
public class Worksheet<T> : IWorksheet where T : IWorksheetItem
{
    public string Name { get; set; }
    public IEnumerable<T> Items { get; set; }
    public Type ItemType => typeof(T);

    // 显式实现非泛型Items属性,完成类型转换
    IEnumerable<IWorksheetItem> IWorksheet.Items => Items;
}

// 调整GetSpreadSheet方法参数类型
public byte[] GetSpreadSheet(IEnumerable<IWorksheet> worksheets)
{
    foreach (var worksheet in worksheets)
    {
        // 反射获取并筛选DateTime相关属性
        var properties = worksheet.ItemType.GetProperties();
        foreach (var prop in properties)
        {
            if (prop.PropertyType == typeof(DateTime) || prop.PropertyType == typeof(DateTime?))
            {
                // 此处添加你的DateTime属性处理逻辑
                Console.WriteLine($"找到DateTime类型属性:{prop.Name}");
            }
        }
    }
    // 后续生成SpreadSheet逻辑
    return new byte[0];
}

// 使用方式
var worksheets = new List<IWorksheet>();
worksheets.Add(worksheet1);
worksheets.Add(worksheet2);
worksheets.Add(worksheet3);

var result = GetSpreadSheet(worksheets);

方案二:利用泛型协变

如果不需要非泛型接口,可以定义一个协变泛型接口(用out关键字标记),因为你的场景中T仅作为输出(如Items是只读的IEnumerable<T>),符合协变的使用条件。

代码实现

// 协变泛型接口,out关键字标记T为输出类型
public interface IWorksheet<out T> where T : IWorksheetItem
{
    string Name { get; set; }
    IEnumerable<T> Items { get; }
    Type ItemType { get; }
}

// 修改Worksheet类实现协变接口
public class Worksheet<T> : IWorksheet<T> where T : IWorksheetItem
{
    public string Name { get; set; }
    public IEnumerable<T> Items { get; set; }
    public Type ItemType => typeof(T);
}

// 调整GetSpreadSheet方法参数
public byte[] GetSpreadSheet(IEnumerable<IWorksheet<IWorksheetItem>> worksheets)
{
    foreach (var worksheet in worksheets)
    {
        var properties = worksheet.ItemType.GetProperties();
        foreach (var prop in properties)
        {
            if (prop.PropertyType == typeof(DateTime) || prop.PropertyType == typeof(DateTime?))
            {
                // 处理DateTime属性逻辑
            }
        }
    }
    return new byte[0];
}

// 使用方式:协变支持直接转换
var worksheets = new List<IWorksheet<IWorksheetItem>>();
worksheets.Add(worksheet1);
worksheets.Add(worksheet2);
worksheets.Add(worksheet3);

var result = GetSpreadSheet(worksheets);

方案对比

  • 方案一:灵活性更强,适合需要在非泛型场景下扩展Worksheet功能的情况,即使后续添加输入型成员(如AddItem(T item))也不受影响。
  • 方案二:代码更简洁,无需额外实现非泛型属性,但仅适用于T仅作为输出的场景(若有接受T作为参数的方法,协变会失效)。

内容的提问来源于stack exchange,提问作者Jason Butera

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 06:23:16