Condividi tramite


Varianza nelle interfacce generiche (Visual Basic)

.NET Framework 4 ha introdotto il supporto della varianza per diverse interfacce generiche esistenti. Il supporto della varianza consente la conversione implicita di classi che implementano queste interfacce. Le interfacce seguenti sono ora varianti:

La Covarianza consente a un metodo di avere un tipo restituito più derivato rispetto a quello definito dal parametro di tipo generico dell'interfaccia. Per illustrare la funzionalità di covarianza, considerare queste interfacce generiche: IEnumerable(Of Object) e IEnumerable(Of String). L'interfaccia IEnumerable(Of String) non eredita l'interfaccia IEnumerable(Of Object) . Tuttavia, il String tipo eredita il Object tipo e, in alcuni casi, è possibile assegnare oggetti di queste interfacce l'uno all'altro. Questo è illustrato nell'esempio di codice seguente.

Dim strings As IEnumerable(Of String) = New List(Of String)
Dim objects As IEnumerable(Of Object) = strings

Nelle versioni precedenti di .NET Framework, questo codice causa un errore di compilazione in Visual Basic con Option Strict On. Ma ora è possibile usare strings invece di objects, come illustrato nell'esempio precedente, perché l'interfaccia IEnumerable<T> è covariante.

La controvarianza consente a un metodo di avere tipi di argomento meno derivati rispetto a quelli specificati dal parametro generico dell'interfaccia. Per illustrare la controvarianza, si supponga di aver creato una BaseComparer classe per confrontare le istanze della BaseClass classe . La classe BaseComparer implementa l'interfaccia IEqualityComparer(Of BaseClass). Poiché l'interfaccia IEqualityComparer<T> è ora controvariante, è possibile usare BaseComparer per confrontare le istanze di classi che ereditano la BaseClass classe . Questo è illustrato nell'esempio di codice seguente.

' 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

Per altri esempi, vedere Uso della varianza nelle interfacce per le raccolte generiche (Visual Basic).For more examples, see Using Variance in Interfaces for Generic Collections (Visual Basic).

La varianza nelle interfacce generiche è supportata solo per i tipi di riferimento. I tipi valore non supportano la varianza. Ad esempio, IEnumerable(Of Integer) non può essere convertito in modo implicito in IEnumerable(Of Object)perché i numeri interi sono rappresentati da un tipo di valore.

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

È anche importante ricordare che le classi che implementano interfacce varianti sono ancora invarianti. Ad esempio, anche se List<T> implementa l'interfaccia IEnumerable<T>covariante , non è possibile convertire List(Of Object) in modo implicito in List(Of String). Questo è illustrato nell'esempio di codice seguente.

' 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)

Vedere anche