【问题标题】:Can type constraints be exclusive rather than inclusive?类型约束可以是排他性的而不是包容性的吗?
【发布时间】:2014-06-20 21:01:30
【问题描述】:

我正在研究一个与 VB.NET 和多个通用接口相关的奇怪问题。我的类通过指定两个不同的泛型类型参数两次实现了泛型接口。为了找到该问题的解决方案(如下所列),我有一个想法,但找不到任何资源来看看这是否可行。

VB.NET Implement Mutliple Contravariant interface types

此处的 MSDN 文档:http://msdn.microsoft.com/en-us/library/d5x73970.aspx 解释了类型约束的使用,这很有帮助但并不完整(或者至少该语言不支持我想要的)。

通常将约束声明为:

Public Interface ICopiesFrom(Of TObject As Class)
    Sub CopyFrom(ByVal data As TObject)
End Interface

但是假设我想排除一个可能的泛型类型参数,而不是限制到一个子集。

Public Sub Interface ICopiesFrom(Of TObject Not As SpecificBadType)

这个可以吗?

看起来像:How to call a generic method with type constraints when the parameter doesn't have these constraints? 是重复的,但我的问题有点不同,因为我想要编译时支持。

编辑:

这是一个示例用例(可能是这样的):

'Ideally, the interface would have a definition like this
Public Interface ICopiesFrom(Of TModel As Not ISecureType)
    Sub CopyFrom(ByVal data As TModel)
End Interface

'Target type to exclude
Public Interface ISecureType

    Property AccountValue As Decimal
    Property AccountNumber As String

End Interface

Public Class AccountModel

    Public Overridable Property AccountCreated As DateTime
    Public Overridable Property ReferredBy As Guid

End Class

Public Class DetailedAccountModel
    Inherits AccountModel
    Implements ISecureType

    Public Property AccountNumber As String Implements ISecureType.AccountNumber
    Public Property AccountValue As Decimal Implements ISecureType.AccountValue

End Class

Public Class ProfileModel

    Public Property UserName As String
    Public Property EmailAddress As String
    Public Property PhoneNumber As String

End Class

Public Class User 'Composite representation for a view
    Implements ICopiesFrom(Of ProfileModel)
    Implements ICopiesFrom(Of AccountModel)

    Public Property UserName As String
    Public Property EmailAddress As String
    Public Property PhoneNumber As String
    Public Property AccountCreated As DateTime
    Public Property ReferredBy As Guid

    Public Overridable Overloads Sub CopyFrom(ByVal data As ProfileModel) Implements ICopiesFrom(Of ProfileModel).CopyFrom
        If data IsNot Nothing Then
            Me.UserName = data.UserName
            Me.EmailAddress = data.EmailAddress
            Me.PhoneNumber = data.PhoneNumber
        End If
    End Sub

    Public Overridable Overloads Sub CopyFrom(ByVal data As AccountModel) Implements ICopiesFrom(Of AccountModel).CopyFrom
        If data IsNot Nothing Then
            Me.AccountCreated = data.AccountCreated
            Me.ReferredBy = data.ReferredBy
        End If
    End Sub

    Public Function AccountAge() As Double
        Return (DateTime.Now - AccountCreated).TotalDays
    End Function

End Class

在上述场景中,我绝不希望有人能够将 DetailedAccountModel 传递给 User 类,这样它就永远不会“意外”显示出来,理想情况下这会在编译时被捕获。

以下任何一个都是可接受的答案:

  • 一种完全实现此目的的方法
  • 实现相同(或类似)结果的替代方法
  • 确认我疯了,这是不可能的(当然有来源)。

【问题讨论】:

  • 约束的要点是告诉编译器约束类型的成员(方法/属性/等)是有效的,所以你可以使用它们,所以简短的回答是否定的,不是方式你正在尝试使用它们。向我们展示您希望在两个不同约束的实现中做什么。
  • @ClickRick 我已经用示例用法更新了我的问题。
  • 我认为不可能
  • @ClickRick:让Foo<U,V> 类型同时实现IFoo<U,V>IFoo<V,U> 怎么样?被禁止是因为UV 可能是同一类型,在这种情况下IFoo<U,V>IFoo<V,U> 将是同一类型但可能具有冲突的方法定义。

标签: .net vb.net generics type-constraints


【解决方案1】:

不,没有办法做到这一点。您可以将ask for it to be considered 作为语言功能,但我认为语言创建者认为这会鼓励人们编写违反开放/封闭原则的代码。

例如,您现在可能知道有一个特定的类不应该用作泛型类型,但是如何阻止其他人提出您的另一种类型现在知道了。您尝试排除特定类型的事实是代码异味,这可能表明存在另一种更好的方法来解决您要解决的问题。也许您在应该使用组合的地方使用继承。也许您可以通过分离接口或使用更好的关注点分离来受益。也许通过不包含此功能,该语言实际上正在帮助我们编写更易于维护的代码。

【讨论】:

  • 我认为这不会违反开放/封闭原则,特别是如果约束的目的是表明某些类型参数不会统一。例如,目前一个类不能同时实现IFoo<T,SomeClass>IFoo<SomeClass,T>,除非编译器知道T 派生自某个SomeClass 不知道的类。我认为这种约束的根本困难在于......
  • ...假设存储位置类型与对象实例类型占用相同的域,具有相同的层次结构,除了一些特定的皱纹(例如,从ValueType 派生的类型的存储位置在他们自己奇怪的宇宙,对于那些来自Nullable<T>的人来说,有一个非常奇怪的角落)。为泛型寻求的约束类型将需要进一步偏离正常的层次模型。
猜你喜欢
  • 1970-01-01
  • 2020-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多