嵌套的CoVariance是否会变成Convarivariance?

时间:2018-12-18 08:56:11

标签: c# covariance contravariance

我了解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();
}

请举例说明嵌套事物如何改变其方差。 或者,请重定向到优质的阅读材料。预先感谢。

1 个答案:

答案 0 :(得分:1)

让我们为引用类型的“是”关系写(一种改进的小于符号)。例如Elephant ⊂ IMammalIMammal ⊂ 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>

这就像在数学中,将不等式的两边都乘以数一样。 XY交换(共同)。

但是,当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中发送“发出”的内容一样。