Udostępnij za pośrednictwem


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:

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)

Koncepcje

Tworzenie interfejsów typu Variant (C# and Visual Basic)

Interfejsy ogólne

Wariancje w delegatach (C# i Visual Basic)