多态泛型

时间:2012-12-23 00:45:10

标签: .net vb.net oop generics polymorphism

我有一个通用类Command(Of T)

命令(部分)定义为:

Public Class Command(Of T As BaseType)
    Inherits Command
    Public Property Condition As Func(Of T, Boolean)
End Class

我想创建一个包含所有命令的列表,然后当我递交一个对象A时,拉出所有与我的A具有相同泛型类型的命令,并调用Condition(A) 1}}返回true

我能做到

Dim B As List(Of BaseType)
B.Add(New DerivedType)

但是

Dim C As New List(Of Command(Of BaseType))
C.Add(New Command(Of DerivedType))

引发转换错误。

我可以让Command继承自非通用对象(让我们称之为CommandBase ...)

Dim C As New List(Of CommandBase)
C.Add(New Command(Of DerivedType))

哪个有效,但现在我无法回到特定类型的引用。这将得到正确的命令对象:

Dim CommandsOfTypeA = B.Where(function(x) x.GetType.GetGenericArguments(0).FullName = A.GetType.FullName)

但我现在看不出怎么办......

Dim MatchingCommands = CommandsOfTypeA.Where(function(x) c.Condition(A))

由于CommandsOfTypeA是List(Of Command)而不是List(Of Command(Of DerivedType))

我错过了什么?

1 个答案:

答案 0 :(得分:1)

问题是虽然DerivedType的实例是BaseType的实例,但这并不一定意味着Command(Of DerivedType)的实例是Command(Of BaseType)的实例}。默认情况下,不考虑类型层次结构的泛型类型参数。

在编程语言理论中,启用此功能的功能称为covariance

.net 4.0确实有一些支持,虽然它只能应用于接口,而不是类。 Here是关于该主题的一些文档。

基本上,它看起来像这样:

Interface ICovariant(Of Out R)
    Function GetSomething() As R
    ' The following statement generates a compiler error. 
    ' Sub SetSomething(ByVal sampleArg As R) 
End Interface

当您的通用类型仅用作方法输入,从不输出或refoutput参数时,这仅适用于(如图所示)。