Condividi tramite


Uso della varianza nelle interfacce per le raccolte generiche (Visual Basic)

Un'interfaccia covariante consente ai metodi di restituire più tipi derivati rispetto a quelli specificati nell'interfaccia. Un'interfaccia controvariante consente ai metodi di accettare parametri di tipi meno derivati rispetto a quelli specificati nell'interfaccia.

In .NET Framework 4 diverse interfacce esistenti sono diventate covarianti e controvarianti. Questi includono IEnumerable<T> e IComparable<T>. In questo modo è possibile riutilizzare i metodi che operano con raccolte generiche di tipi di base per le raccolte di tipi derivati.

Per un elenco di interfacce varianti in .NET Framework, vedere Varianza nelle interfacce generiche (Visual Basic).

Conversione di raccolte generiche

L'esempio seguente illustra i vantaggi del supporto della covarianza nell'interfaccia IEnumerable<T> . Il PrintFullName metodo accetta una raccolta del IEnumerable(Of Person) tipo come parametro. Tuttavia, è possibile riutilizzarlo per una raccolta del IEnumerable(Of Person) tipo perché Employee eredita Person.

' Simple hierarchy of classes.
Public Class Person
    Public Property FirstName As String
    Public Property LastName As String
End Class

Public Class Employee
    Inherits Person
End Class

' The method has a parameter of the IEnumerable(Of Person) type.
Public Sub PrintFullName(ByVal persons As IEnumerable(Of Person))
    For Each person As Person In persons
        Console.WriteLine(
            "Name: " & person.FirstName & " " & person.LastName)
    Next
End Sub

Sub Main()
    Dim employees As IEnumerable(Of Employee) = New List(Of Employee)

    ' You can pass IEnumerable(Of Employee),
    ' although the method expects IEnumerable(Of Person).

    PrintFullName(employees)

End Sub

Confronto di raccolte generiche

Nell'esempio seguente vengono illustrati i vantaggi del supporto della controvarianza nell'interfaccia IComparer<T> . La classe PersonComparer implementa l'interfaccia IComparer(Of Person). Tuttavia, è possibile riutilizzare questa classe per confrontare una sequenza di oggetti del Employee tipo perché Employee eredita Person.

' Simple hierarchy of classes.
Public Class Person
    Public Property FirstName As String
    Public Property LastName As String
End Class

Public Class Employee
    Inherits Person
End Class
' The custom comparer for the Person type
' with standard implementations of Equals()
' and GetHashCode() methods.
Class PersonComparer
    Implements IEqualityComparer(Of Person)

    Public Function Equals1(
        ByVal x As Person,
        ByVal y As Person) As Boolean _
        Implements IEqualityComparer(Of Person).Equals

        If x Is y Then Return True
        If x Is Nothing OrElse y Is Nothing Then Return False
        Return (x.FirstName = y.FirstName) AndAlso
            (x.LastName = y.LastName)
    End Function
    Public Function GetHashCode1(
        ByVal person As Person) As Integer _
        Implements IEqualityComparer(Of Person).GetHashCode

        If person Is Nothing Then Return 0
        Dim hashFirstName =
            If(person.FirstName Is Nothing,
            0, person.FirstName.GetHashCode())
        Dim hashLastName = person.LastName.GetHashCode()
        Return hashFirstName Xor hashLastName
    End Function
End Class

Sub Main()
    Dim employees = New List(Of Employee) From {
        New Employee With {.FirstName = "Michael", .LastName = "Alexander"},
        New Employee With {.FirstName = "Jeff", .LastName = "Price"}
    }

    ' You can pass PersonComparer,
    ' which implements IEqualityComparer(Of Person),
    ' although the method expects IEqualityComparer(Of Employee)

    Dim noduplicates As IEnumerable(Of Employee) = employees.Distinct(New PersonComparer())

    For Each employee In noduplicates
        Console.WriteLine(employee.FirstName & " " & employee.LastName)
    Next
End Sub

Vedere anche