Variância em interfaces genéricas (Visual Basic)

O .NET Framework 4 introduziu o suporte à variância para várias interfaces genéricas existentes. O suporte à variância permite a conversão implícita de classes que implementam essas interfaces. As seguintes interfaces são agora variantes:

A covariância permite que um método tenha um tipo de retorno mais derivado do que o definido pelo parâmetro de tipo genérico da interface. Para ilustrar o recurso de covariância, considere estas interfaces genéricas: IEnumerable(Of Object) e IEnumerable(Of String). A IEnumerable(Of String) interface não herda a IEnumerable(Of Object) interface. No entanto, o String tipo herda o Object tipo e, em alguns casos, você pode querer atribuir objetos dessas interfaces uns aos outros. Isso é mostrado no exemplo de código a seguir.

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

Em versões anteriores do .NET Framework, esse código causa um erro de compilação no Visual Basic com Option Strict On. Mas agora você pode usar strings em vez de objects, como mostrado no exemplo anterior, porque a IEnumerable<T> interface é covariante.

A contravariância permite que um método tenha tipos de argumento que são menos derivados do que o especificado pelo parâmetro genérico da interface. Para ilustrar a contravariância, suponha que você criou uma BaseComparer classe para comparar instâncias da BaseClass classe. A classe BaseComparer implementa a interface IEqualityComparer(Of BaseClass). Como a IEqualityComparer<T> interface agora é contravariante, você pode usar BaseComparer para comparar instâncias de classes que herdam a BaseClass classe. Isso é mostrado no exemplo de código a seguir.

' 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

Para obter mais exemplos, consulte Usando variância em interfaces para coleções genéricas (Visual Basic).

A variância em interfaces genéricas é suportada apenas para tipos de referência. Os tipos de valor não suportam variância. Por exemplo, IEnumerable(Of Integer) não pode ser convertido implicitamente em IEnumerable(Of Object), porque inteiros são representados por um tipo de valor.

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

Também é importante lembrar que as classes que implementam interfaces variantes ainda são invariantes. Por exemplo, embora List<T> implemente a interface IEnumerable<T>covariante, você não pode converter List(Of Object) implicitamente em List(Of String). Isso é ilustrado no exemplo de código a seguir.

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

Consulte também