为什么这个 .NET class 不通过继承接受另一个父 class 作为类型参数?

Why does this .NET class not accept this other parent class as a type parameter via inheritance?

我想弄清楚为什么编译器会抱怨这个(我认为是一个简单的)继承场景:

鉴于此摘要class..

public class AbstractAnimalValidator<TAnimal> : AbstractValidator<TAnimal> 
    where TAnimal: Animal<IFoo, IBar>, new()
{
}

然后我尝试创建这个具体的 class...

public class CatValidator : AbstractAnimalValidator<Cat>{ }

我收到这个错误...

好的,那么 Cat 是什么?

public abstract class Animal<TFoo, TBar>
    where TFoo : IFoo
    where TBar : IBar { }

public class Cat : Animal<RedFoo, CleanBar> { }

我就是不明白:/猫是这两种类型......

现在this is the FULL REPO on .NET Fiddle展示一个实例。

更新 1:

我想我要求的是 1. 为什么 我的代码不起作用? IE。我的大脑说这应该有效,但编译器说:given this scenario XXX .. I wouldn't know what to do ... 2.如何解决这个问题,所以我可以学习。

基本上,我已经多次阅读 covariance/contravariance 的内容,而且我的脑袋一直在爆炸……尤其是一些废话 foo/bar 的例子。希望通过我的 一点点具体 示例,我也许能够更深入地理解这一点。

这是因为 CatAnimal<RedFoo, CleanBar> 的子类,AbstractAnimalValidator 期望是 Animal<IFoo, IBar> 的子类,但 Animal<RedFoo, CleanBar>不是 Animal<IFoo, IBar>的子类型,因此Cat也不是子类型。

请注意,在此术语中,子类型是比子类更通用的术语。如果 B 继承 ABA 的子类,如果 B 类型,BA 的子类对象可以分配给 A 类型变量。

要解决此问题,请使 TFooTBar 类型参数 Covariant。这只允许用于C#中的接口,所以你需要引入一个新的接口:

public interface IAnimal<out TFoo, out TBar>
  where TFoo : IFoo
  where TBar : IBar { }

并像这样使用它:

public class AbstractAnimalValidator<TAnimal>
where TAnimal : IAnimal<IFoo, IBar>, new()
{
}

public abstract class Animal<TFoo, TBar> : IAnimal<TFoo, TBar>
  where TFoo : IFoo
  where TBar : IBar { }

这样Cat就变成了IAnimal<IFoo, IBar>的子类,因为RedFooIFoo的子类,而CleanBar是[=34的子类=].