【问题标题】:Is nested CoVariance becomes Contravariance?嵌套的 CoVariance 会变成逆变吗?
【发布时间】:2018-12-18 08:56:10
【问题描述】:

我将 CoVariance 和 CotraVariance 的概念理解为,当需要将接口标记为 只读 时,我们使用 out TWrite -only 接口我们使用 in 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();
}

请举例说明嵌套事物如何改变它们的方差。 或者请将我重定向到一个好的阅读材料。提前致谢。

【问题讨论】:

  • 该代码中没有嵌套任何内容?
  • 对不起,我没有找到确切的词。这里 IObserver 是 T 上的逆变器。我希望 IObservable 具有 ,因为它需要 IObserver(T 的某个容器)。
  • @Enigmativity 逆变器IObserver&lt;&gt;作为另一个接口的方法Subscribe中的“传入”参数,另一个接口可以合法地声明为协变。
  • 对于阅读材料,Martin Abadi 和 Luca Cardelli 所写的 Theory of Objects 包含有关此主题的部分。

标签: c# covariance contravariance


【解决方案1】:

让我们为引用类型的“is a”关系写(一种修改过的小于号)。例如Elephant ⊂ IMammal,或IMammal ⊂ IAnimal

先看IObserver&lt;&gt;

interface IObserver<in T>
{
    void OnNext(T t);
    // other members irrelevant
}

“in”表示它是逆变的。逆变的意思是:

如果X ⊂ Y,那么IObserver&lt;Y&gt; ⊂ IObserver&lt;X&gt;

相反,当您“在 的两侧应用IObserver&lt;·&gt;”时,XY 的顺序发生了变化。这类似于将不等式(来自数学)乘以两边的 数。您必须交换不等式的两侧(或将 变成)。

之所以允许在T中有IObserver&lt;T&gt;逆变是因为T只用于方法中的值参数(即OnNext)。

假设我们有一个IObserver&lt;IMammal&gt; 的实例。这可以在其OnNext(IMammal t) 方法中接收任何IMammal。这个实例也可以充当IObserver&lt;Elephant&gt; 吗?是的,因为如果它可以接收任何IMmammal,那么它尤其可以接收Elephant,因此逆变是安全可靠的。因为Elephant“是一个”IMammal,那么IObserver&lt;IMammal&gt;“是一个”IObserver&lt;Elephant&gt;

逆变换关系。

现在,让我们看看另一种类型(现在我们来看看您的要求!)。我把它从IObservable&lt;&gt;重命名为IVable&lt;&gt;

interface IVable<out T>
{
    IDisposable Subscribe(IObserver<T> o);
}

“out”表示协变。协变意味着:

如果X ⊂ Y,那么IVable&lt;X&gt; ⊂ IVable&lt;Y&gt;

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

但是当IVable&lt;T&gt; 有一个方法Subscribe 接受“带有T 的东西”时,它怎么可能是协变的呢?那是因为“某物”在T 中是逆变的!

让我们看看它是否安然无恙。所以,假设我们有一个实例是IVable&lt;IMammal&gt;。这意味着它有一个Subscribe,可以接收任何IObserver&lt;IMammal&gt;。但后者是逆变的,所以因为IMammal“是”IAnimal,那么任何IObserver&lt;IAnimal&gt;“是”IObserver&lt;IMammal&gt;。所以这向我们展示了我们的IVable&lt;IMammal&gt; 可以充当IVable&lt;IAnimal&gt;,如协方差所示。所以一切都很好。

结论:在T 中将逆变 的东西“输入”,就像在T 中的“输出”一样。同样,在T 中发送“输出”逆变的东西,就像在T 中发送“输入”一样。

【讨论】:

  • 非常感谢宝贵的 cmets。
猜你喜欢
  • 2019-07-16
  • 1970-01-01
  • 1970-01-01
  • 2014-06-11
  • 2021-12-30
  • 1970-01-01
  • 1970-01-01
  • 2014-08-18
  • 1970-01-01
相关资源
最近更新 更多