« Variance » : différence entre les versions

De Banane Atomic
Aller à la navigationAller à la recherche
Ligne 22 : Ligne 22 :
<kode lang='cs'>
<kode lang='cs'>
var deriveds = new List<Derived>();
var deriveds = new List<Derived>();
List<Base> bases = strings;  // Cannot convert type List<string> to List<object> because List<T> is invariant
List<Base> bases = strings;  // Cannot convert type List<Base> to List<Derived> because List<T> is invariant
IList<Base> bases = strings;  // Cannot implicitly convert type List<string> to IList<object> because IList<T> is invariant
IList<Base> bases = strings;  // Cannot implicitly convert type List<Base> to IList<Derived> because IList<T> is invariant


IEnumerable<Base> bases = deriveds;      // IEnumerable<T> is covariant
IEnumerable<Base> bases = deriveds;      // IEnumerable<T> is covariant

Version du 26 mars 2024 à 17:10

Links

Description

Variance allows to replace a type with a less-derived (covariance: derived → base) type or a more-derived type (contravariance: base → derived).
Covariance enable implicit reference conversion for array types, delegate types, and generic type arguments.
Covariance preserves assignment compatibility and contravariance reverses it.

Since .NET Framework 4, C# supports covariance and contravariance in generic interfaces and delegates and allows for implicit conversion of generic type parameters.

Assignment compatibility

Allow an object of a more derived type (child class, ex: string) to be assigned to an object of a less derived type (parent class, ex: object).

Cs.svg
string s = "test";
object o = s;

Covariance

Allow a generic object of child class type (ex: string) to be assigned to a generic object of parent class type (ex: object).

It works only with covariant interface
Cs.svg
var deriveds = new List<Derived>();
List<Base> bases = strings;   // Cannot convert type List<Base> to List<Derived> because List<T> is invariant
IList<Base> bases = strings;  // Cannot implicitly convert type List<Base> to IList<Derived> because IList<T> is invariant

IEnumerable<Base> bases = deriveds;       // IEnumerable<T> is covariant
IReadOnlyList<Base> bases = deriveds;       // IReadOnlyList<T> is covariant
IReadOnlyCollection<Base> bases = deriveds; // IReadOnlyCollection<T> is covariant

var bases = (IList<Base>)deriveds; // ???

Native covariant interfaces

Interface Since
IEnumerable<out T> .NET Framework 4.0
IReadOnlyList<out T> .NET Framework 4.5
IReadOnlyCollection<out T> .NET Framework 4.5