【问题标题】:Polymorphic generics多态泛型
【发布时间】:2012-12-10 01:51:09
【问题描述】:

我有一个通用类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) 的调用返回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))

我错过了什么?

【问题讨论】:

  • @MattBall 谢谢,我显然有点累了

标签: .net vb.net oop generics polymorphism


【解决方案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 参数时才有效(如图所示)。

【讨论】:

  • 我假设既然 Command 是 Command(Of T As BaseType) 那么每个 Command(Of Anything) 必须 是一个 ``Command(Of BaseType)` 但正如你所说,显然不是被检查。这是正确的方法还是有更好的方法来连接它并且仍然是强类型的?
  • 嗯好的,我认为这对我不起作用,因为我需要我的条件 lambda 基于T
  • @Basic:IEnumerable(of T) 接口是通用的,所以在List(Of Command(Of BaseType)) 不起作用的地方,你可以通过将变量声明为IEnumerable(Of Command(Of BaseType)) 来获得你需要的东西。跨度>
猜你喜欢
  • 2017-08-20
  • 2011-07-10
  • 2017-05-14
  • 1970-01-01
  • 2018-06-07
  • 1970-01-01
  • 1970-01-01
  • 2023-03-05
  • 2014-06-01
相关资源
最近更新 更多