Variant type parameter lists
Variant type parameter lists can only occur on interface and delegate types. The difference from ordinary type-parameter-lists is the optional variance-annotation on each type parameter. variant-type-parameter-list: variant-type-parameters: variance-annotation: If the variance annotation is out, the type parameter is said to be covariant. If the variance annotation is in, the type parameter is said to be contravariant. If there is no variance annotation, the type parameter is said to be invariant. In the example interface C<out X, in Y, Z> Z P { get; set; } X is covariant, Y is contravariant and Z is invariant. 13.1.3.1 Variance safety The occurrence of variance annotations in the type parameter list of a type restricts the places where types can occur within the type declaration. A type T is output-unsafe if one of the following holds: · T is a contravariant type parameter · T is an array type with an output-unsafe element type · T is an interface or delegate type S<A1,… AK> constructed from a generic type S<X1,.. XK> where for at least one Ai one of the following holds: o Xi is covariant or invariant and Ai is output-unsafe. o Xi is contravariant or invariant and Ai is input-safe. A type T is input-unsafe if one of the following holds: · T is a covariant type parameter · T is an array type with an input-unsafe element type · T is an interface or delegate type S<A1,… AK> constructed from a generic type S<X1,.. XK> where for at least one Ai one of the following holds: o Xi is covariant or invariant and Ai is input-unsafe. o Xi is contravariant or invariant and Ai is output-unsafe. Intuitively, an output-unsafe type is prohibited in an output position, and an input-unsafe type is prohibited in an input position. A type is output-safe if it is not output-unsafe, and input-safe if it is not input-unsafe. 13.1.3.2 Variance conversion The purpose of variance annotations is to provide for more lenient (but still type safe) conversions to interface and delegate types. To this end the definitions of implicit (§6.1) and explicit conversions (§6.2) make use of the notion of variance-convertibility, which is defined as follows: A type T<A1, …, An> is variance-convertible to a type T<B1, …, Bn> if T is either an interface or a delegate type declared with the variant type parameters T<X1, …, Xn>, and for each variant type parameter Xi one of the following holds: · Xi is covariant and an implicit reference or identity conversion exists from Ai to Bi · Xi is contravariant and an implicit reference or identity conversion exists from Bi to Ai · Xi is invariant and an identity conversion exists from Ai to Bi
|