将通用类型约束定义为与实现相同的类型

时间:2018-10-23 17:09:59

标签: c# .net class generics interface

我想知道是否可以强制对接口或抽象类通用类型的约束与专门为其实现的具体类相同。

让我们说我们要检查某个实体适合执行任务的能力,并使其在其他人的熟练程度方面与其他人相当

abstract class Entity
{
    public abstract int Fitness(); //Bigger the number - more fit the entity is

    public int MoreFitThan(Entity other)
    {
        return Fitness().CompareTo(other.Fitness());
    }
}

class Fish : Entity
{
    public int swimSpeed { get; set; }

    public override int Fitness()
    {
        return swimSpeed;
    }
}

class Human : Entity
{
    public int testPoints { get; set; }

    public override int Fitness()
    {
        return testPoints;
    }
}

但是现在我们可以将鱼的速度与人类的测试通过能力进行比较,这没有任何意义。

static void Main()
        {
            Human human = new Human() {testPoints = 10};
            Fish fish = new Fish() { swimSpeed = 20 };
            fish.MoreFitThan(human);
        }

那么,有没有一种通用的方法可以使某种类或接口强制其子类仅实现自己的类型与自己的类型比较? 这样,我们只能将人与人进行比较,而将鱼与鱼进行比较,而没有明确指定可比较实体的类型?

2 个答案:

答案 0 :(得分:1)

您可以通过以下方式使用泛型来强制传递给MoreFitThan的类型与继承的类匹配。

abstract class Entity<T> where T : Entity<T>
{
    public abstract int Fitness(); //Bigger the number - more fit the entity is

    public int MoreFitThan(T other)
    {
        return Fitness().CompareTo(other.Fitness());
    }
}

class Fish : Entity<Fish>
{
    public int swimSpeed { get; set; }

    public override int Fitness()
    {
        return swimSpeed;
    }
}

class Human : Entity<Human>
{
    public int testPoints { get; set; }

    public override int Fitness()
    {
        return testPoints;
    }
}

那么以下将是编译错误

Human human = new Human() {testPoints = 10};
Fish fish = new Fish() { swimSpeed = 20 };
fish.MoreFitThan(human);

因为Human不是Fish。但是,这将允许将从Fish继承的类与Fish进行比较。

class Trout : Fish 
{
    public int size { get; set; }

    public override int Fitness()
    {
        return size;
    }
}

以下方法有效,因为TroutFish

Trout trout = new Trout() {size = 10};
Fish fish = new Fish() { swimSpeed = 20 };
fish.MoreFitThan(trout);

答案 1 :(得分:0)

我的建议是创建可比较类型的类,例如:SwimmerRunnerLearner实现您的接口,然后在这些类中同时实现IComparable和对该类类型实施约束。然后,您可以将Human用于Learner,将Fish用于Swimmer来扩展这些类,等等...

还有其他方法可以执行此操作,但这应该可以满足您的需求。