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.
Eine kovariante Schnittstelle ermöglicht es seinen Methoden, mehr abgeleitete Typen zurückzugeben als die in der Schnittstelle angegebenen. Eine kontravariante Schnittstelle ermöglicht es seinen Methoden, Parameter von weniger abgeleiteten Typen als die in der Schnittstelle angegebenen zu akzeptieren.
In .NET Framework 4 wurden mehrere vorhandene Schnittstellen kovariant und kontravariant. Dazu gehören IEnumerable<T> und IComparable<T>. Auf diese Weise können Sie Methoden wiederverwenden, die mit generischen Auflistungen von Basistypen für Sammlungen abgeleiteter Typen arbeiten.
Eine Liste der Variantenschnittstellen in .NET finden Sie unter Variance in Generic Interfaces (C#).
Konvertieren von generischen Auflistungen
Das folgende Beispiel veranschaulicht die Vorteile der Kovarianzunterstützung in der IEnumerable<T> Schnittstelle. Die PrintFullName Methode akzeptiert eine Auflistung des IEnumerable<Person> Typs als Parameter. Sie können dies jedoch für eine Auflistung des Typs IEnumerable<Employee> wiederverwenden, da EmployeePerson erbt.
// Simple hierarchy of classes.
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class Employee : Person { }
class Program
{
// The method has a parameter of the IEnumerable<Person> type.
public static void PrintFullName(IEnumerable<Person> persons)
{
foreach (Person person in persons)
{
Console.WriteLine("Name: {0} {1}",
person.FirstName, person.LastName);
}
}
public static void Test()
{
IEnumerable<Employee> employees = new List<Employee>();
// You can pass IEnumerable<Employee>,
// although the method expects IEnumerable<Person>.
PrintFullName(employees);
}
}
Vergleich generischer Sammlungen
Das folgende Beispiel veranschaulicht die Vorteile der Kontravarianzunterstützung in der IEqualityComparer<T> Schnittstelle. Der PersonComparer-Klasse implementiert die IEqualityComparer<Person>-Schnittstelle. Sie können diese Klasse jedoch wiederverwenden, um eine Abfolge von Objekten des Employee Typs zu vergleichen, da Employee sie erbt Person.
// Simple hierarchy of classes.
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class Employee : Person { }
// The custom comparer for the Person type
// with standard implementations of Equals()
// and GetHashCode() methods.
class PersonComparer : IEqualityComparer<Person>
{
public bool Equals(Person x, Person y)
{
if (Object.ReferenceEquals(x, y)) return true;
if (Object.ReferenceEquals(x, null) ||
Object.ReferenceEquals(y, null))
return false;
return x.FirstName == y.FirstName && x.LastName == y.LastName;
}
public int GetHashCode(Person person)
{
if (Object.ReferenceEquals(person, null)) return 0;
int hashFirstName = person.FirstName == null
? 0 : person.FirstName.GetHashCode();
int hashLastName = person.LastName.GetHashCode();
return hashFirstName ^ hashLastName;
}
}
class Program
{
public static void Test()
{
List<Employee> employees = new List<Employee> {
new Employee() {FirstName = "Michael", LastName = "Alexander"},
new Employee() {FirstName = "Jeff", LastName = "Price"}
};
// You can pass PersonComparer,
// which implements IEqualityComparer<Person>,
// although the method expects IEqualityComparer<Employee>.
IEnumerable<Employee> noduplicates =
employees.Distinct<Employee>(new PersonComparer());
foreach (var employee in noduplicates)
Console.WriteLine(employee.FirstName + " " + employee.LastName);
}
}