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

C#非泛型类中如何存储带指定接口约束的泛型类实例集合?

C# 可以实现该需求,由于C#没有Java中? extends这类泛型通配符语法,我们可以通过抽取非泛型公共父级的方式来达到相同效果,完全满足你的所有约束要求。

实现方案

你只需要把泛型类中不需要泛型参数的公共成员(比如你示例中的Run方法)提取到一个非泛型的抽象基类或者接口中,再让泛型类继承/实现该父级即可。

代码示例(针对你给出的GameAction场景)

第一步:定义非泛型公共基类

// 非泛型抽象基类,只包含不需要泛型参数的公共成员
public abstract class GameActionBase
{
    public abstract bool Run();
}

public interface IGameEntity
{
    // 你的标记接口逻辑
}

第二步:改造原有泛型类继承该基类

abstract class GameAction<T> : GameActionBase where T : IGameEntity
{
    protected T Subject;

    public GameAction(T subject)
    {
        // 这里Subject依然是强类型的T,不需要任何强转
        Subject = subject;
    }

    // 重写基类的Run方法,实现各自子类的业务逻辑
    public override bool Run()
    {
        // 你的业务逻辑,直接使用强类型的Subject即可
        throw new System.NotImplementedException();
    }
}

第三步:改造ActionRunner存储非泛型基类实例

class ActionRunner
{
    // 存储非泛型基类的列表,不需要给ActionRunner加泛型参数
    private List<GameActionBase> actions = new List<GameActionBase>();

    // 可选:封装Add方法做类型约束,避免添加不符合要求的实例
    public void AddAction<T>(GameAction<T> action) where T : IGameEntity
    {
        actions.Add(action);
    }

    public void RunAll()
    {
        foreach (var action in actions)
        {
            // 直接调用基类的Run方法,不需要感知具体泛型参数
            action.Run();
        }
    }
}

方案说明

  • 完全满足你的核心约束:没有给ActionRunner(也就是你一开始说的ContainerClass)添加任何泛型参数
  • 每个泛型GameAction<T>的实例依然保留了精确的泛型参数类型,Subject成员是强类型的具体IGameEntity实现类,不需要在子类中做任何强转
  • 规避了你提到的不允许使用List<MyAbstractClass<MyInterface>>的问题,列表中存储的都是具体泛型类的实例,只是通过非泛型基类做统一聚合

如果你不想用抽象基类,也可以用非泛型接口替换,效果完全一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 17:24:03