编译器如何自动计算协变量和逆变量?

时间:2015-08-26 19:05:39

标签: c# compiler-construction covariance contravariance

请注意这是关于编译器内部的问题。

我刚读过[1],在为泛型类型引入方差时,C#团队正在考虑是否应该自动计算类型是否为共变量或逆变量。当然这是一段历史,但我想知道如何做到这一点?

是采用所有方法(不包括构造函数)并检查类型是否位于inout位置?

[1] Jeffrey Richter,CLR来自C#,第4版,第281页。

1 个答案:

答案 0 :(得分:8)

现在删除的答案中的链接是我的文章,它解释了确定方差有效性的确切规则,但没有回答您的问题。您实际要查找的链接是关于为什么C#编译器团队拒绝尝试在没有任何语法的情况下计算方差的文章,这里是:

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

简而言之,拒绝此类功能的原因是:

  • 该功能需要全程序分析。这不仅价格昂贵,而且意味着一种类型的微小变化会导致许多远方类型的差异选择意外地发生变化。
  • 你想要在一个类型中设计方差;它是一个声明,表明您希望其用户不仅在今天使用该类型,而且永远都是如此。该期望应编入计划文本。
  • 有很多情况下很难计算用户的意图,那么你做了什么?你必须通过要求语法来解决它,所以为什么不只是一直需要它?例如:
interface I<V, W> 
{ 
     I<V, W> M(I<W, V> x);
}

作为练习,计算V和W上所有可能的有效方差注释。现在,编译器应该如何进行相同的计算?你用了什么算法?第二,鉴于这是模棱两可的,你会如何选择解决模糊性?

现在,我注意到目前为止这个答案也没有回答你的问题。你问过如何做到这一点,我给你的全部是我们不应该尝试去做的原因。有很多方法可以做到。

例如,获取程序中的每个泛型类型以及这些泛型类型的每个类型参数。假设有一百个。然后每个只有三到百种可能的组合,包括in,out和out;尝试所有这些,看看哪些工作,然后有一个从获胜者中选择的排名功能。当然,问题在于它需要比宇宙年龄更长的时间才能运行。

现在,我们可以应用智能修剪算法来说“任何选择T在哪里,并且已知在输出位置使用是无效的”,所以不要检查任何这些情况。现在我们有一种情况,我们有数百个这样的谓词必须全部应用,以确定适用的方差有效性集合。正如我在上面的例子中所提到的,弄清楚什么东西实际上处于输入或输出位置是非常棘手的。所以这可能也是一个非首发。

啊,但是这个想法意味着分析关于代数系统的谓词是一种潜在的好技术。我们可以构建一个生成谓词的引擎,然后对它应用复杂的SMT solver。那将是需要大量计算的坏情况,但现代SMT求解器在典型情况下非常好。

但是这一切都是方式,对于对用户几乎没有任何价值的功能来说,要做太多的工作。