Compartilhar via


Variação em interfaces genéricas (C# e Visual Basic)

.NET Framework 4 introduz o suporte de variação para várias interfaces genéricas existentes. Suporte de variação permite a conversão implícita de classes que implementam essas interfaces. As seguintes interfaces são variante agora:

Covariância permite um método para ter 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<Object> e IEnumerable<String> (IEnumerable(Of Object) e IEnumerable(Of String) em Visual Basic). O IEnumerable<String> (IEnumerable(Of String) em Visual Basic) não herda a interface do IEnumerable<Object> interface (IEnumerable(Of Object) em Visual Basic). No entanto, o String tipo herdar o Object tipo e em alguns casos, convém atribuir objetos dessas interfaces entre si. 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
IEnumerable<String> strings = new List<String>();
IEnumerable<Object> objects = strings;

Em versões anteriores do.NET Framework, este código faz com que um erro de compilação em C# e Visual Basic com Option Strict On. Mas agora você pode usar strings em vez de objects, conforme mostrado no exemplo anterior, porque o IEnumerable interface é covariant.

/ Contravariância permite um método para que os tipos de argumento são derivados menos do que o especificado pelo parâmetro genérico da interface. Para ilustrar/contravariância, suponha que você tenha criado um BaseComparer classe para comparar instâncias de BaseClass classe. O BaseComparer classe implementa o IEqualityComparer<BaseClass> interface (IEqualityComparer(Of BaseClass) em Visual Basic). Porque o IEqualityComparer interface é agora contravariant, 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
// 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;
    }
}

Para obter mais exemplos, consulte Usando variação em interfaces para coleções genéricas (C# e Visual Basic).

Variação em interfaces genéricas há suporte para tipos de referência apenas. Tipos de valor não oferecem suporte a variação. Por exemplo, IEnumerable<int> (IEnumerable(Of Integer) em Visual Basic) não pode ser convertido implicitamente em IEnumerable<object> (IEnumerable(Of Object) em Visual Basic), porque os 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
IEnumerable<int> integers = new List<int>();
// The following statement generates a compiler errror, 
// because int is a value type. 
// IEnumerable<Object> objects = integers;

Também é importante lembrar que as classes que implementam interfaces variant são ainda invariável. Por exemplo, embora List implementa a interface covariant IEnumerable, você não pode converter implicitamente List<Object> para List<String> (List(Of Object) para List(Of String) em Visual Basic). This is illustrated in the following code example.

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

Consulte também

Referência

Usando variação em interfaces para coleções genéricas (C# e Visual Basic)

Conceitos

Criando interfaces genéricas variantes (C# e Visual Basic)

Interfaces genéricas

Variação em delegações (C# e Visual Basic)