Variação em Interfaces genéricas (C# e Visual Basic)
.NET Framework 4 introduz o suporte de variação para várias interfaces de genéricos existentes. Suporte de variação permite a conversão implícita de classes que implementam essas interfaces. As seguintes interfaces são variante de agora:
IEnumerable<T>(T é covariant)
IEnumerator<T>(T é covariant)
IQueryable<T>(T é covariant)
IGrouping<TKey, TElement>(TKey e TElement são covariant)
IComparer<T>(O T é contravariant)
IEqualityComparer<T>(O T é contravariant)
IComparable<T>(O T é contravariant)
Covariância permite um método de um tipo de retorno mais derivado daquele 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 de IEnumerable<Object> interface (IEnumerable(Of Object) em Visual Basic). No entanto, o String tipo herdar de Object tipo e em alguns casos, convém 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
IEnumerable<String> strings = new List<String>();
IEnumerable<Object> objects = strings;
Em versões anteriores do.NET Framework, esse código faz com que um erro de compilação em C# e de Visual Basic com Option Strict On. Mas agora você pode usar strings em vez de objects, conforme mostrado no exemplo anterior, porque o IEnumerable<T> interface é covariant.
/ Contravariância permite um método de 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<T> 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 a variação nas Interfaces de coleções genéricas (C# e Visual Basic).
Variação em interfaces genéricas oferece suporte somente para tipos de referência. Tipos de valor não suportam a variação. Por exemplo, IEnumerable<int> (IEnumerable(Of Integer) em Visual Basic) não pode ser convertido implicitamente 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<T> implementa a interface covariant IEnumerable<T>, 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 a variação nas Interfaces de coleções genéricas (C# e Visual Basic)
Conceitos
Criando Interfaces genéricas de variante (C# e Visual Basic)