泛型接口中的方差 (Visual Basic)

.NET Framework 4 引入了对多个现有泛型接口的方差支持。 变体支持允许实现这些接口的类进行隐式转换。 以下接口现在是变体:

协变允许方法具有比接口的泛型类型参数定义的更派生的返回类型。 为了说明协变功能,请考虑以下泛型接口: 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)

另请参阅