泛型介面中的變異數 (Visual Basic)
.NET Framework 4 針對數個現有泛型介面推出了差異支援。 差異支援可讓實作這些介面的類別以隱含方式轉換。 下列介面現在都是 Variant︰
IEnumerable<T> (T 是 Covariant)
IEnumerator<T> (T 是 Covariant)
IQueryable<T> (T 是 Covariant)
IGrouping<TKey,TElement> (
TKey
和TElement
都是 Covariant)IComparer<T> (T 是 Contravariant)
IEqualityComparer<T> (T 是 Contravariant)
IComparable<T> (T 是 Contravariant)
共變數允許方法具有比介面泛型型別參數所定義之衍生程度更大的傳回型別。 若要示範共變數功能,請考慮這些泛型介面︰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 中,此程式碼使用 Option Strict On
造成 Visual Basic 的編譯錯誤。 但現在您可以使用 strings
,而不使用 objects
,如上例所示,因為 IEnumerable<T> 介面是 Covariant。
反變數允許方法具有比介面泛型參數所指定之衍生程度更小的引數型別。 為示範反變數,我們假設您已建立 BaseComparer
類別來比較 BaseClass
類別的執行個體。 BaseComparer
類別會實作 IEqualityComparer(Of BaseClass)
介面。 因為 IEqualityComparer<T> 介面現在是 Contravariant,所以您可以使用 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
請務必牢記,實作 Variant 介面的類別仍然是非變異的。 例如,雖然 List<T> 實作了 Covariant 介面 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)