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

如何表示泛型IHandler<T>的超类型,以声明通用处理程序集合?

问题解答

问题翻译

给定泛型类型IHandler<T>,如何表示它的超类型,以便声明一个List<T2>(其中T2可以是任意IHandler<T>)?

请注意:本问题并非针对列表,列表代码仅为示例需求构造。问题核心涉及开放泛型,方差概念同样适用于此,标题未提及列表。

示例代码(修正后):

public class NotGeneric
{
  private readonly List</* 此处需替换为目标超类型 */> _handlers = new();
  public void AddHandler(IHandler<object> handler) // 此处参数需匹配超类型
  {
    _handlers.Add(handler);
  }
}

解决方案

方案1:定义非泛型基接口(最通用)

给IHandler<T>定义一个非泛型的基接口IHandler,让所有泛型实现都继承这个基接口,这样就能用非泛型接口作为列表的元素类型,兼容任意IHandler<T>实例。

步骤如下:

  1. 声明非泛型基接口:
public interface IHandler
{
    // 可在此定义所有Handler共有的非泛型方法/属性
}

public interface IHandler<T> : IHandler
{
    void Handle(T message);
    // 其他泛型成员
}
  1. 修改NotGeneric类:
public class NotGeneric
{
  private readonly List<IHandler> _handlers = new();
  
  public void AddHandler(IHandler handler)
  {
    _handlers.Add(handler);
  }
}

这种方式不受泛型方差限制,不管T是引用类型还是值类型,所有IHandler<T>实例都能存入列表。

方案2:利用泛型协变(仅适用于引用类型T)

如果IHandler<T>的泛型参数是输出型(即仅作为方法返回值,不作为参数),可以将接口标记为协变(使用out关键字),此时可以用IHandler<object>作为超类型(仅支持引用类型的T)。

步骤如下:

  1. 声明协变接口:
public interface IHandler<out T>
{
    T GetResult();
    // 注意:协变接口中T不能作为方法参数类型
}
  1. 修改NotGeneric类:
public class NotGeneric
{
  private readonly List<IHandler<object>> _handlers = new();
  
  public void AddHandler(IHandler<object> handler)
  {
    _handlers.Add(handler);
  }
}

此时,任意引用类型的IHandler<SomeReferenceType>都能隐式转换为IHandler<object>并存入列表,但值类型(如int、DateTime)的IHandler<T>无法转换,因为.NET不支持值类型的泛型协变。

注意事项

  • 如果需要兼容所有类型的T(包括值类型),优先选择方案1的非泛型基接口方式。
  • 协变方案仅适用于T为引用类型,且接口仅将T作为输出的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 18:32:43