<out T>
denotes that T
is covariant.
It seems plausible that a sequence of giraffes can be treated as a sequence of animals. "Covariance" of an interface means that "if there is an implicit reference conversion from Giraffe
to Animal
then there is also an implicit reference conversion from I<Giraffe>
to I<Animal>
. The convertibility of the constructed type "varies in the same direction" as the convertibility of the type arguments.
Example:
// Valid! // Invalid!
// Every giraffe is an animal // Not every animal is a giraffe
IEnumerable<Giraffe> giraffes = ...; IEnumerable<Animal> animals = ...;
IEnumerable<Animal> animals = giraffe; IEnumerable<Giraffe> giraffes = animals;
Animal animal = animals.First(); Giraffe giraffe = giraffes.First();
<in T>
denotes that T
is contravariant.
It seems plausible that code which can compare two animals can also compare two giraffes. "Contravariance" of an interface is the same as covariance with the direction reversed. It means that "if there is an implicit reference conversion from Giraffe
to Animal
then there is also an implicit reference conversion from I<Animal>
to I<Giraffe>
. The convertibility of the constructed type "varies in the opposite direction" as the convertibility of the type arguments.
Example:
// Valid! // Invalid!
// Animal comparer can compare // Giraffe comparer cannot compare
// giraffes // arbitrary animals
IComparer<Animal> animalC = ...; IComparer<Giraffe> giraffeC = ...;
IComparer<Giraffe> giraffeC = animalC; IComparer<Animal> animalC = giraffeC;
int result = giraffeC.Compare(x, y); int result = animalC.Compare(x, y);
See: