if covariant, contravariant or bivariant; invariant or nonvariant if not variant. The article considers how this applies to some common type constructors. C# examples For example, in C#, if is a subtype of , then: is a subtype of . The subtyping is preserved because is covariant on . is a subtype of . The subtyping is reversed because is contravariant on . Neither nor is a subtype of the other, because is invariant on . The variance of a C# generic interface is declared by placing the (covariant) or (contravariant) attribute on (zero or more of) its type parameters. For each so-marked type parameter, the compiler conclusively verifies, with any violation being fatal, that such use is globally consistent. The above interfaces are declared as , , and . Types with more than one type parameter may specify different variances on each type parameter. For example, the delegate type represents a function with a contravariant input parameter of type and a covariant return value of type . The typing rules for interface variance ensure type safety. For example, an represents a first-class function expecting an argument of type , and a function that can handle any type of animal can always be used instead of one that can only handle cats. Arrays Read-only data types (sources) can be covariant; write-only data types (sinks) can be contravariant. Mutable data types which act as both sources and sinks should be invariant. To illustrate this general phenomenon, consider the array type. For the type we can make the type , which is an "array of animals". For the purposes of this example, this array supports both reading and writing elements. We have the option to treat this as either: covariant: a is an ; contravariant: an is a ; invariant: an is not a and a is not an . If we wish to avoid type errors, then only the third choice is safe. Clearly, not every can be treated as if it were a , since a client reading from the array will expect a , but an may contain e.g. a . So the contravariant rule is not safe. Conversely, a cannot be treated as an . It should always be possible to put a into an . With covariant arrays this cannot be guaranteed to be safe, since the backing store might actually be an array of cats. So