Wariancje w interfejsach (C# i Visual Basic)
.NET Framework 4 wprowadzono obsługę wariancji dla kilku istniejących interfejsów rodzajowy.Obsługa odchylenie umożliwia niejawna konwersja klasy, które implementują te interfejsy.Następujące interfejsy są teraz wariantu:
IEnumerable(T jest kowariantnego)
IEnumerator(T jest kowariantnego)
IQueryable(T jest kowariantnego)
IGrouping(TKey and TElement are covariant)
IComparer(T jest kontrawariantnego)
IEqualityComparer(T jest kontrawariantnego)
IComparable(T jest kontrawariantnego)
Kowariancja pozwala metody mają bardziej pochodny typ zwracany niż określone przez parametr typu rodzajowego interfejsu.Aby zilustrować funkcja KOWARIANCJA, należy wziąć pod uwagę te interfejsy rodzajowy: IEnumerable<Object> i IEnumerable<String> (IEnumerable(Of Object) i IEnumerable(Of String) w języku Visual Basic).IEnumerable<String> (IEnumerable(Of String) w języku Visual Basic) interfejsu nie dziedziczą IEnumerable<Object> interfejsu (IEnumerable(Of Object) w języku Visual Basic).Jednakże String typu dziedziczą Object typu, a w niektórych przypadkach można przypisać obiektów tych interfejsów.To jest pokazane w następującym przykładzie kodu.
Dim strings As IEnumerable(Of String) = New List(Of String)
Dim objects As IEnumerable(Of Object) = strings
IEnumerable<String> strings = new List<String>();
IEnumerable<Object> objects = strings;
We wcześniejszych wersjach.NET Framework ten kod powoduje błąd kompilacji w C# i Visual Basic z Option Strict On.Teraz można używać, ale strings zamiast objects, jak pokazano w poprzednim przykładzie, ponieważ IEnumerable interfejsu jest kowariantnego.
Kontrawariancja pozwala na metody mają typy argumentów, które są mniej pochodny, niż określona przez parametr rodzajowy interfejs.Aby zilustrować kontrawariancja, założono, że użytkownik utworzył BaseComparer klasy do porównywania wystąpień BaseClass klasy.BaseComparer Klasy implementuje IEqualityComparer<BaseClass> interfejsu (IEqualityComparer(Of BaseClass) w języku Visual Basic).Ponieważ IEqualityComparer interfejsu jest teraz kontrawariantnego, można użyć BaseComparer do porównywania wystąpień klas, które dziedziczą BaseClass klasy.To jest pokazane w następującym przykładzie kodu.
' Simple hierarchy of classes.
Class BaseClass
End Class
Class DerivedClass
Inherits BaseClass
End Class
' Comparer class.
Class BaseComparer
Implements IEqualityComparer(Of BaseClass)
Public Function Equals1(ByVal x As BaseClass,
ByVal y As BaseClass) As Boolean _
Implements IEqualityComparer(Of BaseClass).Equals
Return (x.Equals(y))
End Function
Public Function GetHashCode1(ByVal obj As BaseClass) As Integer _
Implements IEqualityComparer(Of BaseClass).GetHashCode
Return obj.GetHashCode
End Function
End Class
Sub Test()
Dim baseComparer As IEqualityComparer(Of BaseClass) = New BaseComparer
' Implicit conversion of IEqualityComparer(Of BaseClass) to
' IEqualityComparer(Of DerivedClass).
Dim childComparer As IEqualityComparer(Of DerivedClass) = baseComparer
End Sub
// 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;
}
}
Aby uzyskać więcej przykładów, zobacz Korzystanie z wariancji w interfejsach dla kolekcji (C# i Visual Basic).
Odchylenie w interfejsach rodzajowy jest obsługiwana dla tylko typy odwołań.Typów wartości nie obsługują wariancji.Na przykład IEnumerable<int> (IEnumerable(Of Integer) w języku Visual Basic) nie można niejawnie przekonwertować na IEnumerable<object> (IEnumerable(Of Object) w języku Visual Basic), ponieważ liczby całkowite są reprezentowane przez typ wartości.
Dim integers As IEnumerable(Of Integer) = New List(Of Integer)
' The following statement generates a compiler error
' with Option Strict On, because Integer is a value type.
' Dim objects As IEnumerable(Of Object) = integers
IEnumerable<int> integers = new List<int>();
// The following statement generates a compiler errror,
// because int is a value type.
// IEnumerable<Object> objects = integers;
Jest również pamiętać, że klasy, które implementują interfejsy typu variant są nadal niezmienne.Na przykład Chociaż List implementuje interfejs kowariantnego IEnumerable, nie można niejawnie przekonwertować List<Object> do List<String> (List(Of Object) do List(Of String) w języku Visual Basic).Ilustruje to poniższy przykład kodu.
' The following statement generates a compiler error
' because classes are invariant.
' Dim list As List(Of Object) = New List(Of String)
' You can use the interface object instead.
Dim listObjects As IEnumerable(Of Object) = New List(Of String)
// 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>();
Zobacz też
Informacje
Korzystanie z wariancji w interfejsach dla kolekcji (C# i Visual Basic)