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

C#中如何存储带不同泛型参数的泛型类列表并调用方法?

解决方案:利用泛型接口的协变特性实现需求

问题核心在于C#的泛型类不支持协变,而泛型接口可以通过out关键字实现协变,这是解决不同泛型参数实例统一管理的关键。以下是具体实现步骤:

1. 定义Dto基类与子类

// Dto基类
public class DtoBase { }
// 具体Dto子类
public class Dto1 : DtoBase { }
public class Dto2 : DtoBase { }

2. 定义支持协变的泛型接口

通过out关键字标记泛型参数为输出型,允许子类泛型实例隐式转换为父类泛型接口类型:

// 协变消息接口
public interface IBaseMessage<out T> where T : DtoBase
{
    void Embed();
    // 若需获取Dto,返回T的方法也兼容协变
    T GetDto();
}

// 协变主题接口
public interface IBaseTopic<out T> where T : DtoBase
{
    IBaseMessage<T> Order();
}

3. 修改抽象类实现协变接口

让原有的泛型抽象类实现上述接口:

// 抽象消息类
public abstract class BaseMessage<T> : IBaseMessage<T> where T : DtoBase
{
    public abstract void Embed();
    public abstract T GetDto();
}

// 抽象主题类
public abstract class BaseTopic<T> : IBaseTopic<T> where T : DtoBase
{
    public abstract IBaseMessage<T> Order();
}

4. 实现具体业务类

// 具体消息类1
public class Message1 : BaseMessage<Dto1>
{
    public override void Embed()
    {
        Console.WriteLine("Message1执行Embed操作");
    }

    public override Dto1 GetDto()
    {
        return new Dto1();
    }
}

// 具体主题类1
public class Topic1 : BaseTopic<Dto1>
{
    public override IBaseMessage<Dto1> Order()
    {
        return new Message1();
    }
}

// 具体消息类2
public class Message2 : BaseMessage<Dto2>
{
    public override void Embed()
    {
        Console.WriteLine("Message2执行Embed操作");
    }

    public override Dto2 GetDto()
    {
        return new Dto2();
    }
}

// 具体主题类2
public class Topic2 : BaseTopic<Dto2>
{
    public override IBaseMessage<Dto2> Order()
    {
        return new Message2();
    }
}

5. 统一管理与调用

创建协变接口类型的列表,即可容纳不同泛型参数的主题实例:

// 创建包含不同泛型参数的主题列表
var topics = new List<IBaseTopic<DtoBase>>
{
    new Topic1(),
    new Topic2()
};

// 遍历调用方法
foreach (var topic in topics)
{
    var message = topic.Order();
    message.Embed();
    // 若需处理Dto,可通过DtoBase接收
    DtoBase dto = message.GetDto();
}

关键说明

  • 泛型接口的out关键字是核心:它允许将IBaseTopic<Dto1>隐式转换为IBaseTopic<DtoBase>,因为Dto1是DtoBase的子类,协变特性满足这种向上转型需求。
  • 若你的Embed方法需要接收T作为输入参数,则不能使用out,此时需调整方法参数为DtoBase类型,或重新设计逻辑避免输入型泛型参数的协变冲突。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 08:25:17