Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
.NET Framework 4 hat die Varianzunterstützung für mehrere vorhandene generische Schnittstellen eingeführt. Die Varianzunterstützung ermöglicht die implizite Konvertierung von Klassen, die diese Schnittstellen implementieren.
Ab .NET Framework 4 sind die folgenden Schnittstellen Varianten:
IEnumerable<T> (T ist kovariant)
IEnumerator<T> (T ist kovariant)
IQueryable<T> (T ist kovariant)
IGrouping<TKey,TElement> (
TKeyundTElementsind kovariant)IComparer<T> (T ist kontravariant)
IEqualityComparer<T> (T ist kontravariant)
IComparable<T> (T ist kontravariant)
Ab .NET Framework 4.5 sind die folgenden Schnittstellen variantenfähig:
IReadOnlyList<T> (T ist kovariant)
IReadOnlyCollection<T> (T ist kovariant)
Bei der Kovarianz kann eine Methode einen abgeleiteteren Rückgabetyp haben als den, der durch den generischen Typparameter der Schnittstelle definiert wurde. Um das Kovarianzfeature zu veranschaulichen, betrachten Sie die folgenden allgemeinen Schnittstellen: IEnumerable<Object> und IEnumerable<String>. Die IEnumerable<String> Schnittstelle erbt die IEnumerable<Object> Schnittstelle nicht. Der String Typ erbt jedoch den Object Typ, und in einigen Fällen können Sie Objekte dieser Schnittstellen einander zuweisen. Dies wird im folgenden Codebeispiel demonstriert.
IEnumerable<String> strings = new List<String>();
IEnumerable<Object> objects = strings;
In früheren Versionen von .NET Framework verursacht dieser Code einen Kompilierungsfehler in C# und falls Option Strict vorhanden, in Visual Basic. Jetzt können Sie jedoch anstelle von strings, wie im vorherigen Beispiel gezeigt, verwendenobjects, da die IEnumerable<T> Schnittstelle kovariant ist.
Contravariance ermöglicht es einer Methode, Argumenttypen zu haben, die weniger abgeleitet sind als die durch den generischen Parameter der Schnittstelle angegebenen. Um die Kontravarianz zu veranschaulichen, gehen Sie davon aus, dass Sie eine BaseComparer Klasse erstellt haben, um Instanzen der BaseClass Klasse zu vergleichen. Der BaseComparer-Klasse implementiert die IEqualityComparer<BaseClass>-Schnittstelle. Da die IEqualityComparer<T>-Schnittstelle jetzt kontravariant ist, können Sie BaseComparer verwenden, um Instanzen von Klassen zu vergleichen, die die BaseClass-Klasse erben. Dies wird im folgenden Codebeispiel demonstriert.
// 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;
}
}
Weitere Beispiele finden Sie unter Verwenden der Varianz in Schnittstellen für generische Auflistungen (C#).
Die Varianz in generischen Schnittstellen wird nur für Referenztypen unterstützt. Werttypen unterstützen keine Varianz. Beispielsweise kann IEnumerable<int> nicht implizit in IEnumerable<object> umgewandelt werden, da ganze Zahlen durch einen Werttyp dargestellt werden.
IEnumerable<int> integers = new List<int>();
// The following statement generates a compiler error,
// because int is a value type.
// IEnumerable<Object> objects = integers;
Es ist auch wichtig zu beachten, dass Klassen, die Variantenschnittstellen implementieren, immer noch invariant sind. Obwohl List<T> die kovariante Schnittstelle IEnumerable<T> implementiert, können Sie List<String> nicht implizit in List<Object> konvertieren. Dies wird im folgenden Codebeispiel veranschaulicht.
// 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>();