【问题标题】:VB generics with constraints -- type casting and inheritance?带有约束的 VB 泛型——类型转换和继承?
【发布时间】:2013-02-23 03:24:54
【问题描述】:

以这个场景为例:

Public Interface IMyClass
End Interface

Public mustinherit class MyBaseClass : implements IMyClass
End Class

public class MyClass : inherits MyBaseClass
End Class

public class MyModel(of t as IMyClass)

    private Dim _parameter as t

    Public Sub New(byval parameter As t)
        _parameter As t
    End Sub
End class

在我的控制器中,我可以毫无问题地做到这一点:

Dim _myclass as IMyClass = new MyClass()

我可以用这个做类似的事情吗:

Dim _myModel as MyModel(of IMyClass) = new MyModel(of MyClass)

???

我最初的想法是错误的,因为我认为转换可以自动完成,但似乎并没有完成。有什么方法可以在 .NET 中实现相同的目标?

编辑 我更新了 MyModel 类以显示更多我在做什么。我想限制我创建的实例,然后使用传统的非泛型代码进行缩小转换。基本上,我的部分 Razor 视图需要显式模型,而这些视图最终会渲染另一个视图,该视图将采用该模型并显示它。因为模型都实现或继承了实现 IMyClass 的类,所以所有方法都应该存在于所有实例上,并且应该是可调用的,但类型是不可互换的。

【问题讨论】:

  • 这适用于 c#,但这将适用于您的情况。 stackoverflow.com/questions/1078423/…
  • 指的是一个列表,而不是单个实例。
  • 编辑了我想要做的事情。 @DanielA.White,如果您能给我举个例子说明在这种情况下如何应用,我将不胜感激。 List(of T) 的用例是有道理的,但我不能 100% 确定在这种情况下如何应用它。
  • @ps2goat 另一个答案仅使用List 作为另一种泛型类型,但解释并非特定于List,它适用于您的情况。

标签: vb.net generics inheritance .net-4.0


【解决方案1】:

让我们稍微修改一下MyModel,好吗?

Public Class MyModel(Of T As IMyClass)
    Private _parameter As T

    Public Sub Something(parameter As T)
        _parameter = parameter
    End Sub
End class

Public Class MyClassA : Inherits MyBaseClass
End Class

Public Class MyClassB : Inherits MyBaseClass
End Class

Dim _myModel As MyModel(Of IMyClass) = New MyModel(Of MyClassA)()
_myModel.Something(New MyClassB()) ' Boom!

如果允许分配,最后一行将产生问题:MyMode(Of MyClassA)._parameter 的类型为 MyClassA,但最后一行将分配一个(不相关的)类型为 MyClassB 的对象。这是非法的,所以 VB 禁止这样做。

【讨论】:

    【解决方案2】:

    您需要多种 MyModel,还是只是试图要求将存储的对象限制为 IMyClass?

    最简单的方法(可能无法满足您的所有需求):

    Public Interface IMyClass
        Sub DoIt()
    End Interface
    
    Public Class MyModel
        Private ReadOnly _parameter As IMyClass
        Public Sub New(parameter As IMyClass)
            _parameter = parameter
        End Sub
        Public Sub DoItToIt()
            _parameter.DoIt()
        End Sub
    End Class
    
    Public Class MyClassA
        Implements IMyClass
        Public Sub DoIt() Implements IMyClass.DoIt
        End Sub
    End Class
    
    Public Class Tests
        Public Sub Main()
            Dim model1 As MyModel = New MyModel(New MyClassA)
            model1.DoItToIt()
        End Sub
    End Class
    

    复杂性的下一步是为包含 IMyClass 的类定义接口IHasMyClass。这支持基于所包含对象的允许类型和实际类型的操作:

    Public Interface IMyClass
        Sub DoIt()
    End Interface
    
    Public Interface IHasMyClass
        Function GetIt() As IMyClass
        Function GetItsType() As Type
        Function GetAllowedType() As Type
    End Interface
    
    Public Class MyModel(Of T As IMyClass)
        Implements IHasMyClass
    
        Private ReadOnly _parameter As IMyClass
        Public Sub New(parameter As IMyClass)
            _parameter = parameter
        End Sub
        Public Sub DoItToIt()
            _parameter.DoIt()
        End Sub
    
        Public Function GetItAsT() As T
            Return _parameter
        End Function
    
        Public Function GetIt() As IMyClass Implements IHasMyClass.GetIt
            Return _parameter
        End Function
    
        Public Function GetItsType() As Type Implements IHasMyClass.GetItsType
            Return _parameter.GetType()
        End Function
    
        Public Function GetAllowedType() As Type Implements IHasMyClass.GetAllowedType
            Return GetType(T)
        End Function
    End Class
    
    Public Class MyClassA
        Implements IMyClass
        Public Sub DoIt() Implements IMyClass.DoIt
        End Sub
    End Class
    
    Public Class Tests
        Public Sub Main()
            ' Allow any IMyClass
            Dim model1 As MyModel(Of IMyClass) = New MyModel(Of IMyClass)(New MyClassA)
            model1.DoItToIt()
            Dim it As IMyClass = model1.GetIt()
            Dim allowedT As Type = model1.GetAllowedType()
    
            ' Restrict to MyClassA
            Dim modelA As MyModel(Of MyClassA) = New MyModel(Of MyClassA)(New MyClassA)
            modelA.DoItToIt()
            Dim itA1 As IMyClass = modelA.GetIt()
            Dim itA2 As MyClassA = modelA.GetItAsT()
            Dim allowedTA As Type = modelA.GetAllowedType()
        End Sub
    End Class
    

    在 Tests() 中,请注意我们现在需要声明我们是创建一个接受任何 IMyClass MyModel(Of IMyClass) 的 MyModel,还是一个需要特定子类 MyModel(Of MyClassA) 的 MyModel。

    如果我们要操作 MyModels,可能是上述任何一种类型,我们使用通用接口:

    Dim model As IHasMyClass
    model = model1
    ...
    model = modelA
    

    或者在您的情况下,要支持 MyModel 的所有功能,请将 IHasMyClass 重命名为 IMyModel,并添加各种 MyModel 功能,但不要使用 T,而是使用 IMyClass

    Public Interface IMyModel
        Function GetIt() As IMyClass
        Function GetItsType() As Type
        Function GetAllowedType() As Type
    
        Sub DoItToIt()
        Function CompareIt(other As IMyClass) As Integer
    End Interface
    

    并对 IMyClass 和 MyModel 进行适当的更改/添加。

    那么就可以这样做了:

    Dim model As IMyModel = modelA
    If model.CompareIt(model1.GetIt()) > 0 ...
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多