Contravariance

suggest change

When is an IComparer<T> a subtype of a different IComparer<T1>? When T1 is a subtype of T. IComparer is contravariant in its T parameter, which means that IComparer’s subtype relationship goes in the opposite direction as T’s.

class Animal { /* ... */ }
class Dog : Animal { /* ... */ }

IComparer<Animal> animalComparer = /* ... */;
IComparer<Dog> dogComparer = animalComparer;  // IComparer<Animal> is a subtype of IComparer<Dog>
// animalComparer = dogComparer;  // Compilation error - IComparer<Dog> is not a subtype of IComparer<Animal>

An instance of a contravariant generic type with a given type parameter is implicitly convertible to the same generic type with a more derived type parameter.

This relationship holds because IComparer consumes Ts but doesn’t produce them. An object which can compare any two Animals can be used to compare two Dogs.

Contravariant type parameters are declared using the in keyword, because the parameter must be used only as an input.

interface IComparer<in T> { /* ... */ }

A type parameter declared as contravariant may not appear as an output.

interface Bad<in T>
{
    T GetT();  // type error
}

Feedback about page:

Feedback:
Optional: your email if you want me to get back to you:


Generics:
* Contravariance

Table Of Contents
17 Regex
19 Arrays
21 Enum
22 Tuples
24 GUID
27 Looping
36 Casting
46 Methods
57 Generics
88 Events
92 Structs
104 Indexer
106 Stream
107 Timers
109 Threading
127 Caching
135 Pointers
147 C# Script