我了解CoVariance和CotraVariance的概念,因为当接口需要标记为只读时,我们就使用 out T 并用于 Write -仅界面,我们在T中使用 ,以确保在获取和设置对象的东西方面具有类型安全性。但是,当我们嵌套这些时,ContraVariance如何被视为CoVariance。例如:
interface IObservable<out T>
{
IDisposable Subscribe(IObserver<T> o);
}
interface IObserver<in T>
{
void OnNext(T t);
void OnError(Exception e);
void OnCompleted();
}
请举例说明嵌套事物如何改变其方差。 或者,请重定向到优质的阅读材料。预先感谢。
答案 0 :(得分:1)
让我们为引用类型的“是”关系写⊂
(一种改进的小于符号)。例如Elephant ⊂ IMammal
或IMammal ⊂ IAnimal
。
先看看IObserver<>
:
interface IObserver<in T>
{
void OnNext(T t);
// other members irrelevant
}
“ in”表示它是反变的。相反意味着:
如果为
X ⊂ Y
,则为IObserver<Y> ⊂ IObserver<X>
。
相反的原因是,当您“在X
的两侧都应用Y
时,IObserver<·>
和⊂
的顺序会改变。这类似于将不等式(来自数学)乘以两侧的负数。您必须交换不等式的两个方面(或将⊂
变成⊃
)。
之所以允许IObserver<T>
中的T
有变数,是因为T
仅用于方法(即OnNext
)中的值参数。 / p>
假设我们有一个IObserver<IMammal>
的实例。这可以采用其IMammal
方法中的任何OnNext(IMammal t)
。此实例还可以充当IObserver<Elephant>
吗?是的,因为如果它可以接受任何IMmammal
,那么特别是它可以接受Elephant
,因此这种逆向是安全无害的。因为Elephant
是一个IMammal
,所以IObserver<IMammal>
是一个IObserver<Elephant>
。
逆差使关系逆转。
现在,让我们看看另一种类型(现在我们来看看您要问的!)。我将其从IObservable<>
重命名为IVable<>
:
interface IVable<out T>
{
IDisposable Subscribe(IObserver<T> o);
}
“输出”表示协变。协变表示:
如果为
X ⊂ Y
,则为IVable<X> ⊂ IVable<Y>
。
这就像在数学中,将不等式的两边都乘以正数一样。 X
和Y
被不交换(共同)。
但是,当IVable<T>
的方法Subscribe
接受“带有T
的东西”时,如何协变呢?这是因为“ {某物”在T
中是相反的!
让我们看看它是否安全可靠。因此,假设我们有一个实例IVable<IMammal>
。这意味着它有一个Subscribe
,可以容纳任何IObserver<IMammal>
。但是后者是互变的,因此因为IMammal
是“ IAnimal
”,所以任何IObserver<IAnimal>
“都是” IObserver<IMammal>
。因此,这表明我们IVable<IMammal>
可以充当IVable<IAnimal>
,如协方差所示。所以一切都很好。
结论:在T
中采用“引入”是相反的的东西,就像在T
中采用“ out”一样。同样,在T
中发送“发出” 相反的内容,就像在T
中发送“发出”的内容一样。