Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
.NET Framework 4 heeft variantieondersteuning geïntroduceerd voor verschillende bestaande algemene interfaces. Variantieondersteuning maakt impliciete conversie mogelijk van klassen die deze interfaces implementeren.
Vanaf .NET Framework 4 zijn de volgende interfaces variant:
IEnumerable<T> (T is covariant)
IEnumerator<T> (T is covariant)
IQueryable<T> (T is covariant)
IGrouping<TKey,TElement> (
TKeyenTElementzijn covariant)IComparer<T> (T is contravariant)
IEqualityComparer<T> (T is contravariant)
IComparable<T> (T is contravariant)
Vanaf .NET Framework 4.5 zijn de volgende interfaces variant:
IReadOnlyList<T> (T is covariant)
IReadOnlyCollection<T> (T is covariant)
Met covariantie kan een methode een meer afgeleid retourtype hebben dan dat is gedefinieerd door de algemene typeparameter van de interface. Als u de covariantiefunctie wilt illustreren, kunt u de volgende algemene interfaces overwegen: IEnumerable<Object> en IEnumerable<String>. De IEnumerable<String> interface neemt de IEnumerable<Object> interface niet over. Het String type neemt echter het Object type over en in sommige gevallen wilt u mogelijk objecten van deze interfaces aan elkaar toewijzen. Dit wordt weergegeven in het volgende codevoorbeeld.
IEnumerable<String> strings = new List<String>();
IEnumerable<Object> objects = strings;
In eerdere versies van .NET Framework veroorzaakt deze code een compilatiefout in C# en, indien Option Strict ingeschakeld, in Visual Basic. Maar nu kunt u strings in plaats van de objects gebruiken, zoals wordt weergegeven in het vorige voorbeeld, omdat de IEnumerable<T> interface covariant is.
Met contravariantie kan een methode argumenttypen hebben die minder zijn afgeleid dan die zijn opgegeven door de algemene parameter van de interface. Als u de contravariantie wilt illustreren, gaat u ervan uit dat u een BaseComparer klasse hebt gemaakt om exemplaren van de BaseClass klasse te vergelijken. Met de klasse BaseComparer wordt de IEqualityComparer<BaseClass>-interface geïmplementeerd. Omdat de IEqualityComparer<T> interface nu contravariant is, kunt u exemplaren BaseComparer van klassen vergelijken die de BaseClass klasse overnemen. Dit wordt weergegeven in het volgende codevoorbeeld.
// Simple hierarchy of classes.
class BaseClass { }
class DerivedClass : BaseClass { }
// Comparer class.
class BaseComparer : IEqualityComparer<BaseClass>
{
public int GetHashCode(BaseClass baseInstance)
{
return baseInstance.GetHashCode();
}
public bool Equals(BaseClass x, BaseClass y)
{
return x == y;
}
}
class Program
{
static void Test()
{
IEqualityComparer<BaseClass> baseComparer = new BaseComparer();
// Implicit conversion of IEqualityComparer<BaseClass> to
// IEqualityComparer<DerivedClass>.
IEqualityComparer<DerivedClass> childComparer = baseComparer;
}
}
Zie Afwijking gebruiken in interfaces voor algemene verzamelingen (C#) voor meer voorbeelden.
Variantie in algemene interfaces wordt alleen ondersteund voor referentietypen. Waardetypen bieden geen ondersteuning voor variantie. Kan bijvoorbeeld IEnumerable<int> niet impliciet worden geconverteerd naar IEnumerable<object>, omdat gehele getallen worden vertegenwoordigd door een waardetype.
IEnumerable<int> integers = new List<int>();
// The following statement generates a compiler error,
// because int is a value type.
// IEnumerable<Object> objects = integers;
Het is ook belangrijk te onthouden dat klassen die variantinterfaces implementeren, nog steeds invariant zijn. Bijvoorbeeld, hoewel List<T> de covariant-interface IEnumerable<T> implementeert, kunt u List<String> niet impliciet omzetten naar List<Object>. Dit wordt geïllustreerd in het volgende codevoorbeeld.
// The following line generates a compiler error
// because classes are invariant.
// List<Object> list = new List<String>();
// You can use the interface object instead.
IEnumerable<Object> listObjects = new List<String>();