【问题标题】:(Double) Recursive generic parameters(双)递归泛型参数
【发布时间】:2014-01-02 09:25:13
【问题描述】:

我正在尝试像这样将两个接口链接在一起:

Public Interface A(Of Out T As B(Of A(Of T)))
    ...
End Interface
Public Interface B(Of Out T As A(Of B(Of T)))
    ...
End Interface

问题是我收到错误“类型参数A(Of T) 不继承或实现约束类型A(Of B(Of A(Of T)))”,但为什么不呢?

T 确实继承自 B(Of A(Of T)) 并且是 Out 泛型类型,对吧?

更新:这种构造的原因是,在实现 A 时,我希望通过将类型参数 T 设置为接口B 带有类型参数的原始类,像这样:

Class AA
    Implements A(Of BB)
    ...
End Class
Class BB
    Implements B(Of AA)
    ...
End Class

每个接口将具有一个功能:

Public Interface A(Of Out T As B(Of A(Of T)))
    Function getB() As T
End Interface
Public Interface B(Of Out T As A(Of B(Of T)))
    ReadOnly Property myA As T
End Interface

函数getB返回B的一个实例,函数myA返回A的链接实例。也许还有另一种设计方法,但我仍然想知道我得到的错误实际上意味着什么。希望有人明白我为什么会收到这个错误。

【问题讨论】:

  • 也许如果您能解释实现这些接口的两个类之间的关系意味着什么,我们或许可以建议正确的注释(或告诉您您要强制执行的内容)在泛型中不可强制执行)
  • 我认为您试图实现的目标在泛型中无法执行 - 它似乎 类似于 与 Eric Lippert 的 Curiouser and curiouser blog post 中给出的示例(它是 C# 但相同限制适用于 VB)
  • 我提供的答案确实为您提供了您想要的东西。您可以一直保持强类型的双递归类结构。

标签: .net vb.net generics inheritance constraints


【解决方案1】:

你可以像这样做我认为你想做的事:

Public Interface A(Of TA As A(Of TA, TB), Out TB As B(Of TA, TB))
    Function GetB() As TB
End Interface

Public Interface B(Of Out TA As A(Of TA, TB), TB As B(Of TA, TB))
    ReadOnly Property myA() As TA
End Interface

然后像这样定义你的类:

Public Class AA
    Implements A(Of AA, BB)
    Public Function GetB() As BB Implements A(Of AA, BB).GetB
        Return New BB()
    End Function
End Class

Public Class BB
    Implements B(Of AA, BB)
    Public ReadOnly Property myA() As AA Implements B(Of AA, BB).myA
        Get
            Return New AA()
        End Get
    End Property
End Class

这对我来说是编译和工作的。

您甚至可以使用抽象类来实现这一点,以摆脱 Implements 语法,如下所示:

Public MustInherit Class XA(Of TA As A(Of TA, TB), TB As B(Of TA, TB))
    Implements A(Of TA, TB)
    Public MustOverride Function GetB() As TB Implements A(Of TA, TB).GetB
End Class

Public MustInherit Class XB(Of TA As A(Of TA, TB), TB As B(Of TA, TB))
    Implements B(Of TA, TB)
    Public MustOverride ReadOnly Property myA() As TA Implements B(Of TA, TB).myA
End Class

Public Class AA
    Inherits XA(Of AA, BB)
    Public Overrides Function GetB() As BB
        Return New BB()
    End Function
End Class

Public Class BB
    Inherits XB(Of AA, BB)
    Public Overrides ReadOnly Property myA() As AA
        Get
            Return New AA()
        End Get
    End Property
End Class

【讨论】:

  • 哇,我没想到这是可能的!这正是我的意思。谢谢!
【解决方案2】:

我认为你让自己很难受。为什么要将接口 A 和 B 转换为泛型类型?我猜这是因为您希望方法 myA 和 getB 的实现具有与返回的具体类实例(即 AA 和 BB)相匹配的返回类型。问问自己为什么需要这个; AA 或 BB 类中是否存在接口 A 或 B 中缺少的公共/朋友方法?如果是这样,那么这可能是代码异味的迹象;你可能想要重构。

Robert C. Martin 的一些明智的话:“依赖抽象。不要依赖具体。”

Public Interface A
    Function getB() As B
End Interface

Public Interface B
    ReadOnly Property myA As A
End Interface

Public Class AA
    Implements A

    Public Function getB() As B       ' the return type is still B
        Return New BB()               ' but the return value is an instance of BB
    End Function
End Class

Public Class BB
    Implements B

    Public ReadOnly Property myA As A ' the return type is still A
        Get
            Return New AA()           ' but the return value is an instance of AA
        End Get
    End Property
End Class

至于你的最后一个问题:我理解你的好奇心,但是再深入挖掘错误的确切原因是浪费时间。在我自己的痛苦经历中,当你遇到这样的错误时,这只是意味着你走错了路;重新考虑和重构你的代码!

【讨论】:

  • 是的,你是对的,这个解决方案就是我最终要做的。它并不能真正解释错误,但无论如何我都会接受。谢谢你的解释!
猜你喜欢
  • 2020-02-06
  • 2018-01-02
  • 1970-01-01
  • 2012-08-15
  • 2016-05-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多