【问题标题】:Polymorphism in VB.Net when dealing with GenericsVB.Net 中处理泛型时的多态性
【发布时间】:2012-01-06 16:28:06
【问题描述】:

我有一个名为Modify 的函数。它是这样定义的:

Public Function Modify(Of SIMType As {New, DAOBase})(ByVal obj As DAOBase) As Boolean

你可以看到这个函数是通用的。它将 DAOBase 或 DAOBase 子类的对象作为参数。

在修改函数内部有一个这样的调用:

DAOToGP(obj)

这就是多态性发挥作用的地方。我为DAOBase 创建了四个左右的子类。我为这些类型中的每一种都写了一个DAOToGP()。因此,在Modify() 函数中,当它调用DAOToGP(obj) 时,应该会启动多态性,并且它应该调用DAOToGP() 的正确实现,具体取决于我传递给Modify() 的类型。

但是,我收到以下错误:

Error   20  Overload resolution failed because no accessible 'DAOToGP' can be called without a narrowing conversion:
'Public Shared Function DAOToGP(distributor As Distributors) As Microsoft.Dynamics.GP.Vendor': Argument matching parameter 'distributor' narrows from 'SierraLib.DAOBase' to 'IMS.Distributors'.
'Public Shared Function DAOToGP(product As Products) As Microsoft.Dynamics.GP.SalesItem': Argument matching parameter 'product' narrows from 'SierraLib.DAOBase' to 'IMS.Products'. C:\Users\dvargo.SIERRAWOWIRES\Documents\Visual Studio 2010\Projects\SIM\Dev_2\SIM\IMS\DVSIMLib\GP\GPSIMRunner\Runners\RunnerBase.vb 66  39  IMS

我在这里有点不知所措。我不确定为什么它无法确定要调用哪个函数。有什么想法吗?

【问题讨论】:

    标签: .net vb.net polymorphism


    【解决方案1】:

    您必须将obj 指定为SIMType 而不是DAOBase

    Public Function Modify(Of SIMType As {New, DAOBase})(ByVal obj As SIMType) As Boolean
    

    否则你的泛型类型参数将毫无用处。


    编辑:

    您的 DAOToGP 函数具有不同的签名,并且显然不是从基类派生的。试试这个:

    Public Class DAOBase(Of Tin, Tout)
        Public Function DAOToGP(ByVal obj As Tin) As Tout
        End Function
    End Class
    
    Public Module Test_DAOBase
        Public Function Modify(Of Tin, Tout)(ByVal obj As DAOBase(Of Tin, Tout)) As Boolean
        End Function
    End Module
    

    您还可以将 DAOBAse 声明为抽象类 (MustInherit),将 DAOToGP 声明为抽象函数 (MustOverride):

    Public MustInherit Class DAOBase(Of Tin As {New}, Tout)
        Public MustOverride Function DAOToGP(ByVal obj As Tin) As Tout
    End Class
    
    Public Class DAOProduct
        Inherits DAOBase(Of Products, SalesItem)
    
        Public Overrides Function DAOToGP(ByVal obj As Products) As SalesItem
            Return Nothing
        End Function
    End Class
    
    Public Module Test_DAOBase
        Public Function Modify(Of Tin As {New}, Tout)(ByVal obj As DAOBase(Of Tin, Tout)) As Boolean
            Dim out As Tout = obj.DAOToGP(New Tin())     'This is OK
        End Function
    
        Public Sub TestModify()
            Dim daoProd = New DAOProduct()
            Modify(daoProd)  'This is OK
        End Sub
    End Module
    

    然后为不同的参数类型组合声明从DAOBase 继承的不同类(在我的示例中为DAOProduct)。

    【讨论】:

    • SIMTye 在函数中的几个不同位置使用。但是为什么重载解析会失败呢?为什么找不到正确的DAOToGP() 版本来使用
    【解决方案2】:

    您要做的是在运行时根据参数的运行时类型执行重载解析。但是 VB 重载是在编译时而不是运行时解决的。 (除非您使用Option Strict Off,否则请参阅。)

    顺便说一下,问题与泛型的使用无关——在非泛型例程中也是一样的。

    对于这么少的类型,最好的解决方案可能是一个简单的If 块。

    If obj Is TypeOf subclassone Then
      Dim obj1 As subclassone
      obj1 = obj
      DAOToGP(obj1)
    ElseIf obj Is TypeOf subclasstwo Then
      Dim obj2 As subclasstwo
      obj2 = obj
      DAOToGP(obj2)
      'and so on... 
    

    或者您可以使用array of delegates indexed by System.Type,如similar question中所示

    另一种方法是使用Option Strict Off,然后写

    Dim objWhatever As Object
    objWhatever = obj
    DAOToGP(obj)  ' resolved at runtime, might Throw
    

    但我不推荐这样做,因为Option Strict Off 禁用了一些非常有用的编译器检查。

    【讨论】:

      猜你喜欢
      • 2023-03-05
      • 1970-01-01
      • 2011-07-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-11
      • 2018-01-19
      相关资源
      最近更新 更多