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
相关产品推荐
相关产品推荐

