复杂泛型中的方差无效

时间:2014-05-07 11:13:48

标签: c# generics compiler-errors covariance contravariance

我抓住了这个典型的编译错误:

  

无效方差:类型参数' K'必须是共同有效的   ' ConsoleApplication3.IQuery&#39 ;. ' K'是逆变的。

我熟悉Covariance and Contravariance in C#的基础知识,但我仍然无法理解错误原因:

interface IQuery<in D>
{
}

interface IDct<in K>
{
}
         // error here ↓
interface IDctQuery<in K> : IQuery<IDct<K>>
{
}

请解释我

UPD

有趣的是,此代码完全有效:

interface IQuery<out D>
{
}

interface IDct<out K>
{
}

interface IDctQuery<out K> : IQuery<IDct<K>>
{
}

1 个答案:

答案 0 :(得分:3)

正在发生的事情是,通过使用逆变类型作为另一种逆向类型的类型参数,可以反转类型参数K的方向。听起来令人困惑,但这很好用:

interface IDctQuery<in K> : IQuery<K>
{
}

因为K在IDctQueryIQuery中是逆变的。但是,一旦将IDct添加为类型参数,对K的要求现在就是协变的。所以你需要改为

interface IDctQuery<out K> : IQuery<IDct<K>>
{
}

假设您有两个班级DogAnimalDogAnimal,协变接口保留了这种关系。因此IEnumerable<Dog>可以分配给IEnumerable<Animal>

逆变界面扭转了这种关系。因此,IQuery<Animal>可以分配给IQuery<Dog> IDct<Animal>可以分配给IDct<Dog>

您的界面声明:

interface IDctQuery<in K> : IQuery<IDct<K>>
{
}

表示IDctQuery<Animal>可以分配给IDctQuery<Dog>,因为IQuery<IDct<Animal>>可以分配到IQuery<IDct<Dog>>,因为IQuery是逆变的表示 IDct<Dog>可以分配到IDct<Animal> ,但这不是真的,因为IDict是逆变的,IDct<Animal>可以分配给IDct<Dog>但不是相反。