I catched this typical compilation error:
Invalid variance: The type parameter 'K' must be covariantly valid on 'ConsoleApplication3.IQuery'. 'K' is contravariant.
I am familiar with the basics of Covariance and Contravariance in C#, but I still can't get why it is wrong:
interface IQuery<in D>
{
}
interface IDct<in K>
{
}
// error here ↓
interface IDctQuery<in K> : IQuery<IDct<K>>
{
}
Please, explain me
UPD
It is interesting that this code is completely valid:
interface IQuery<out D>
{
}
interface IDct<out K>
{
}
interface IDctQuery<out K> : IQuery<IDct<K>>
{
}
What is happening is that by using a contravariant type as a type parameter of another contravariat type, that reverses the direction of the type parameter K. Sounds confusing, but this works fine:
interface IDctQuery<in K> : IQuery<K>
{
}
because K is contravariant in IDctQuery and IQuery. But once you add IDct as a type parameter, the requirement on K is now to be covariant. So you need to change to
interface IDctQuery<out K> : IQuery<IDct<K>>
{
}
Lets say you have two classes, Dog and Animal. A Dog is an Animal and a covariant interface preserves this relationship. So IEnumerable<Dog> can be assigned to an IEnumerable<Animal>.
A contravariant interface reverses this relationship. So an IQuery<Animal> can be assigned to an IQuery<Dog> and an IDct<Animal> can be assigned to an IDct<Dog>.
Your interface declaration:
interface IDctQuery<in K> : IQuery<IDct<K>>
{
}
says that an IDctQuery<Animal> can be assigned to an IDctQuery<Dog> from that it follows that IQuery<IDct<Animal>> can be assigned to IQuery<IDct<Dog>> and because IQuery is contravariant it means that IDct<Dog> can be assigned to IDct<Animal> which is not true because IDict is contravariant and IDct<Animal> can be assigned to an IDct<Dog> but not the other way around.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With