如果你考虑一下的话,这就很有意义了Animal
s and Dog
s.
我们先来制定一些具体的实现:
class AnimalHandler: IHandler<Animal> {
public void SetNext(IHandler<Animal> next) {
// animal handlers can handle cats :)
next.Handle(new Cat());
}
// ...
}
class DogHandler: IHandler<Dog> { ... }
由于类型参数IHandler
是逆变的,aIHandler<Animal>
是一种IHandler<Dog>
:
IHandler<Animal> someAnimalHandler = new AnimalHandler();
IHandler<Dog> dogHandler = someAnimalHandler;
假设你的SetNext
方法允许在中声明IHandler
,然后我可以打电话SetNext
和另外一个IHandler<Dog>
在此dogHandler
,因为这正是那种类型dogHandler.SetNext
接受。
IHandler<Dog> anotherDogHandler = new DogHandler();
dogHandler.SetNext(anotherDogHandler);
但这应该是不可能的!毕竟,dogHandler
实际上存储了一个实例AnimalHandler
, whose SetNext
方法接受IHandler<Animal>
, and a IHandler<Dog>
不一定是一个IHandler<Animal>
, 是吗?想象一下如果实施的话会发生什么AnimalHandler.SetNext
实际上运行 - 请记住next
参数是一个DogHandler
- 我们会请训狗师来照顾一只猫!
因此,声明无效SetNext
与逆变TEvent
.
这是更准确地指定的here。据说该类型IHandler<TEvent>
is 输入不安全,因此禁止作为参数。
TEvent
对于要编译的两个接口方法来说,它必须是不变的。