为什么这个.NET类不能通过继承接受这个其他父类作为类型参数?

时间:2015-03-16 09:39:42

标签: .net generics inheritance covariance contravariance

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

鉴于这个抽象类......

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

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

public class CatValidator : AbstractAnimalValidator<Cat>{ }

我收到此错误...

enter image description here

好的,那么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.如何解决这个问题,以便我可以学习。

基本上,我已经多次读过协方差/反函数的东西而且我的脑袋一直在喋喋不休...特别是有一些废话foo / bar的例子。希望通过我的一点点具体的示例,我可能只能再多了一点。

1 个答案:

答案 0 :(得分:1)

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

请注意,在这个术语中,子类型是一个更通用的术语,然后是子类。如果B继承A,则BA的子类,如果B类型,则AB的子类型可以将对象分配给A类型变量。

要解决此问题,请将TFooTBar类型参数协变。这仅适用于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的子类,CleanBarIBar的子类