我抓住了这个典型的编译错误:
无效方差:类型参数' 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>>
{
}
答案 0 :(得分:3)
正在发生的事情是,通过使用逆变类型作为另一种逆向类型的类型参数,可以反转类型参数K的方向。听起来令人困惑,但这很好用:
interface IDctQuery<in K> : IQuery<K>
{
}
因为K在IDctQuery
和IQuery
中是逆变的。但是,一旦将IDct
添加为类型参数,对K的要求现在就是协变的。所以你需要改为
interface IDctQuery<out K> : IQuery<IDct<K>>
{
}
假设您有两个班级Dog
和Animal
。 Dog
是Animal
,协变接口保留了这种关系。因此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>
但不是相反。