【问题标题】:Covariance and Contravariance inference in C# 4.0C# 4.0 中的协方差和逆变推理
【发布时间】:2010-04-28 21:55:05
【问题描述】:

当我们在 C# 4.0 中定义我们的接口时,我们可以将每个泛型参数标记为inout。如果我们尝试将泛型参数设置为 out 并且会导致问题,编译器会引发错误,不允许我们这样做。

问题:

如果编译器有办法推断covariance (out) 和contravariance(in) 的有效用途,为什么我们必须这样标记接口?让我们像往常一样定义接口还不够吗?当我们尝试在客户端代码中使用它们时,如果我们尝试以不安全的方式使用它们会引发错误?

示例:

interface MyInterface<out T> {
    T abracadabra();
}
//works OK

interface MyInterface2<in T> {
    T abracadabra();
}
//compiler raises an error.
//This makes me think that the compiler is cappable 
//of understanding what situations might generate 
//run-time problems and then prohibits them.

还有,

这不是Java在相同情况下所做的吗?据我记得,你只是做类似的事情

IMyInterface<? extends whatever> myInterface; //covariance
IMyInterface<? super whatever> myInterface2; //contravariance

还是我在混合?

谢谢

【问题讨论】:

    标签: c# java generics covariance contravariance


    【解决方案1】:

    如果编译器有办法推断协变(出)和逆变(入)的有效用途,为什么我们必须这样标记接口?

    我不太确定我是否理解这个问题。我想你在问两件事。

    1) 编译器可以推导出方差注释吗?

    2) 为什么 C# 不像 Java 那样支持调用点变化?

    第一个答案是:

    interface IRezrov<V, W> 
    {
        IRezrov<V, W> Rezrov(IRezrov<W, V> x);
    }
    

    我邀请您尝试推断 V 和 W 上所有合法的可能差异注释。您可能会感到惊讶。

    如果你不能为这个方法找出一个唯一的最佳方差注释,你为什么认为编译器可以?

    这里有更多原因:

    http://blogs.msdn.com/ericlippert/archive/2007/10/29/covariance-and-contravariance-in-c-part-seven-why-do-we-need-a-syntax-at-all.aspx

    更笼统地说:您的问题表明推理错误。廉价地检查解决方案是否正确的能力在逻辑上并不意味着有一种廉价的方法可以找到正确的解决方案。例如,对于两千位素数 p 和 q,计算机可以轻松验证 p * q == r 是真还是假。这并不意味着很容易取 r 并找到满足等式的 p 和 q。编译器可以轻松检查方差注释是否正确;这并不意味着它可以在潜在的数十亿个可能的注释中找到正确的方差注释。

    第二个答案是:C# 不是 Java。

    【讨论】:

    • 我认为他的第二个问题更像是“C# 的方差注释与 Java 的通配符类型有何不同?”
    • @Gabe:C# 确实存在 declaration-site 差异。 Java 确实有 call-site 变化。可以肯定,调用站点差异是一个有趣的想法,但让我感觉很奇怪,根据它在特定站点的使用方式来使类型变体,而不是根据定义的行为方式。
    • 是的,我现在明白了 Java 使用的问题所在。它的好处是不必将接口的参数声明为 in 或 out,但是某些客户端现在可能会给它一些用途,如果我打算更新我的接口,以后可能不支持。
    • 实际上,在您的 Rezrov 示例中,只有 4 种情况:V 和 T 可以同时输入或输出(或不输入,但这不算数)。还是我错了?无论如何,您不需要检查所有情况,只需检查客户端代码尝试运行的情况。也就是说,当您尝试编译以某种方式使用接口的代码时,您只需检查一些内容。
    • 很好。 也不错。其中哪一项是正确的选择?现在假设一个调用者使用 V 作为协变,另一个使用它作为逆变。哪一个得到错误?还是两者都有效?
    【解决方案2】:

    好的,这是我所问问题的答案(来自 Eric 的回答):http://blogs.msdn.com/ericlippert/archive/2007/10/29/covariance-and-contravariance-in-c-part-seven-why-do-we-need-a-syntax-at-all.aspx

    首先,在我看来,差异 应该是你的东西 故意设计成你的 接口或委托。让它只是 在不受控制的情况下开始发生 用户反对该目标,并且 可以引入重大更改。 (更多的 在以后的帖子中讨论!)

    自动这样做也意味着 随着开发过程的进行和 方法被添加到接口, 界面的变化可能会改变 不料。这可以引入 意想不到的深远变化 程序中的其他地方。

    我决定在这里明确发布,因为尽管他的链接确实可以回答我的问题,但帖子本身却没有。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多