Заметка
Доступ к этой странице требует авторизации. Вы можете попробовать войти в систему или изменить каталог.
Доступ к этой странице требует авторизации. Вы можете попробовать сменить директорию.
Платформа .NET Framework 4 представила поддержку дисперсии для нескольких существующих универсальных интерфейсов. Поддержка ковариантности обеспечивает автоматическое преобразование классов, реализующих эти интерфейсы. Следующие интерфейсы теперь являются вариантами:
IEnumerable<T> (T является ковариантным)
IEnumerator<T> (T является ковариантным)
IQueryable<T> (T является ковариантным)
IGrouping<TKey,TElement> (
TKeyиTElementковариантные)IComparer<T> (T является контравариантным)
IEqualityComparer<T> (T является контравариантным)
IComparable<T> (T является контравариантным)
Ковариация позволяет методу иметь более производный тип возвращаемого значения, чем определенный параметром универсального типа интерфейса. Чтобы проиллюстрировать функцию ковариации, рассмотрим следующие универсальные интерфейсы: IEnumerable(Of Object) и IEnumerable(Of String). Интерфейс IEnumerable(Of String) не наследует IEnumerable(Of Object) интерфейс. Однако тип String наследует Object тип, и в некоторых случаях может потребоваться назначить объекты этих интерфейсов друг другу. Это показано в следующем примере кода.
Dim strings As IEnumerable(Of String) = New List(Of String)
Dim objects As IEnumerable(Of Object) = strings
В более ранних версиях .NET Framework этот код вызывает ошибку компиляции в Visual Basic.Option Strict On Но теперь можно использовать strings вместо objects, как показано в предыдущем примере, потому что интерфейс IEnumerable<T> является ковариантным.
Контравариантность позволяет методу иметь типы аргументов, которые являются менее производными, чем указанные универсальным параметром интерфейса. Чтобы проиллюстрировать контравариантность, предположим, что вы создали BaseComparer класс для сравнения экземпляров BaseClass класса. Класс BaseComparer реализует интерфейс IEqualityComparer(Of BaseClass).
IEqualityComparer<T> Так как интерфейс теперь является контравариантным, можно использовать BaseComparer для сравнения экземпляров классов, наследующих BaseClass класс. Это показано в следующем примере кода.
' 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
Дополнительные примеры см. в разделе "Использование дисперсии в интерфейсах для универсальных коллекций (Visual Basic)".
Ковариантность в универсальных интерфейсах поддерживается только для ссылочных типов. Типы значений не поддерживают дисперсию. Например, IEnumerable(Of Integer) нельзя неявно преобразовать IEnumerable(Of Object)в , так как целые числа представлены типом значения.
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
Также важно помнить, что классы, реализующие интерфейсы вариантов, по-прежнему инвариантны. Например, хотя List<T> реализует ковариантный интерфейс IEnumerable<T>, нельзя неявно преобразовать List(Of Object) в List(Of String). Это показано в следующем примере кода.
' 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)