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

C#中如何确保泛型类型为类的基类?解决动物分组问题

问题:C#实现动物实例安全加入对应组的类型约束

原始代码

用户的初始代码结构如下,需要解决泛型类型占位符???的类型安全问题:

public abstract class Animal
{
    protected List<List<???>> _groups;

    public Animal(List<List<???>> groups)
    {
        _groups = groups;

        foreach (List<???> group in groups)
        {
            group.Add(this);    
        }
    }
}


public abstract class Mammal : Animal
{
    public Mammal(List<List<???>> groups) : base(groups)
    {
    }
}

public class Dog : Mammal
{
    public Dog(List<List<???>> groups) : base(groups)
    {
    }
}

需求说明

创建动物实例时,需要传入其所属的所有组(比如List<Mammal>或List<Animal>),要求:

  • 动物只能加入类型兼容的组(例如Dog可以加入Mammal或Animal组,但不能加入Duck组)
  • 动物能同时加入所有符合类型要求的组

用户尝试过的泛型约束写法在C#中不被支持:

public class Dog : Mammal
{
    public Dog(List<List<T>> groups) : base(groups) where Dog : T
    {
    }
}

解决方案:通过类型检查实现类型安全

不需要复杂的泛型类,直接在基类构造函数中验证组的元素类型是否兼容当前实例类型,即可实现需求:

public abstract class Animal
{
    protected List<IList> _groups = new List<IList>();

    public Animal(params IList[] groups)
    {
        foreach (var group in groups)
        {
            // 获取组的泛型元素类型
            var elementType = group.GetType().GetGenericArguments()[0];
            // 验证当前实例是否可以被该组容纳(元素类型是当前类的基类或自身)
            if (elementType.IsAssignableFrom(GetType()))
            {
                group.Add(this);
                _groups.Add(group);
            }
            else
            {
                throw new ArgumentException($"无法将{GetType().Name}加入类型为{elementType.Name}的组");
            }
        }
    }

    // 从所有组中移除当前动物的方法
    public void Kill()
    {
        foreach (var group in _groups)
        {
            group.Remove(this);
        }
    }
}

public abstract class Mammal : Animal
{
    public Mammal(params IList[] groups) : base(groups)
    {
    }
}

public class Dog : Mammal
{
    public Dog(params IList[] groups) : base(groups)
    {
    }
}

public class Duck : Animal
{
    public Duck(params IList[] groups) : base(groups)
    {
    }
}

使用示例

// 定义不同类型的组
var mammalGroup = new List<Mammal>();
var animalGroup = new List<Animal>();
var duckGroup = new List<Duck>();

// 正确:Dog可以加入Mammal和Animal组
var dog = new Dog(mammalGroup, animalGroup);

// 错误:尝试将Dog加入Duck组会抛出ArgumentException
// var invalidDog = new Dog(duckGroup);

// 正确:Duck可以加入Animal组
var duck = new Duck(animalGroup);

// 错误:尝试将Duck加入Mammal组会抛出ArgumentException
// var invalidDuck = new Duck(mammalGroup);

方案优势

  1. 无需修改原有类的继承结构,仅在基类构造函数中添加类型检查
  2. 自动验证组的兼容性,避免错误的类型加入
  3. 支持任意层级的继承关系(如Dog→Mammal→Animal)
  4. 保留了Kill方法从所有组中移除实例的功能

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 20:26:07