代码之家  ›  专栏  ›  技术社区  ›  magallanes

vb6相当于list<someclass>

  •  10
  • magallanes  · 技术社区  · 13 年前

    我想知道是否存在一个等价的(.net)

    list<somefixedclass> 
    

    在VB6中

    我知道vb6中存在集合,但它使用对象(变量)而不是特定对象。

    谢谢。

    4 回复  |  直到 13 年前
        1
  •  22
  •   Cody Gray iPhone Developer    13 年前

    在VB 6中没有与泛型直接等效的 List<T> 在vb.net中找到。然而,有这样一件事 Collection 在VB 6中,它提供了类似的功能。主要的区别是一个vb 6 收藏 不是强类型 ,这意味着所有对象都存储为 Variants 在集合中。在某些情况下,这是有益的,因为它允许您在同一集合中存储许多不同类型的数据,实际上,VB在内部使用此对象。很容易使用 收藏 以及向上投射对象,因为它们是从类中检索到的,但您几乎无能为力。不能在VB运行时实现强类型集合。

    也就是说,有一个变通方案可以实现。与在引入泛型之前如何在vb.net的早期版本中实现集合类似, 你可以把 收藏 在类中,只有 收藏 是通过从此类公开的方法 . 这种设计模式通常被称为 “自定义集合” .

    这确实有自动处理强制转换的好处,并且减少了代码的使用者必须记住这样的实现细节。它考虑了(极有可能)在运行时循环通过一个集合的可能性,该集合只包含一种类型的对象,但意外添加了第二种不兼容的对象类型,从而导致代码引发异常。当然,缺点是您必须重新实现 收藏 以自定义集合上的公共方法的形式对自己进行对象化。

    下面是一个例子,说明您可能会怎么做:

    Public Class CustomerCollection
    
        ''#Internal collection, exposed by this class
        Private m_Customers As Collection
    
        Private Sub Class_Initialize()
            ''#Set up the internal collection
            Set m_Customers = New Collection
        End Sub
    
        Public Sub Add(ByVal cust as Customer, Optional ByVal key as String)
            ''#Add the Customer object to the internal collection
            If IsMissing(key) Then
                m_Customers.Add cust
            Else
                m_Customers.Add cust, key
            End If
        End Sub
    
        Public Property Get Count() As Integer
            ''#Return the number of objects in the internal collection
            Count = m_Customers.Count
        End Property
    
        Public Sub Remove(ByVal index As Variant)
            ''#Remove the specified object from the internal collection,
            ''# either by its index or its key
            m_Customers.Remove index
        End Sub
    
        Public Function Item(ByVal index As Variant) as Customer
            ''#Return the specified object from the internal collection,
            ''# either by its index or its key
            Set Item = m_Customers.Item(index)
        End Function
    
        Public Sub Clear()
            ''#Removes all objects from the internal collection
            Set m_Customers = New Collection
        End Sub
    
    End Class
    

    请注意,为了设置自定义集合的 Item 属性作为集合的默认方法(如内置 收藏 对象),需要在VB 6 IDE中执行以下步骤:

    1. 从“工具”菜单中,单击“过程属性”

    2. 从“名称”组合框中选择自定义类的名称。

    3. 当对话框出现时,单击“高级”按钮。

    4. 在“过程ID”组合框中选择“(默认)”项。

    5. 点击“确定”


    如果您还希望允许使用 For Each 语法(也像内置的 收藏 对象),可以添加 NewEnum 自定义类的函数:

    Public Property Get NewEnum() As IUnknown
        ''#Provides support for enumeration using For Each
        Set NewEnum = m_Customers.[_NewEnum]
    End Property
    

    完成后,需要指示vb使用此属性:

    1. 如前所述,从“工具”菜单打开“过程属性”对话框。

    2. 从“名称”组合框中选择自定义类的名称。

    3. 当对话框出现时,单击“高级”按钮。

    4. 在“过程ID”组合框中键入数字“-4”。

    5. 点击“确定”

        2
  •  5
  •   Kris Erickson    13 年前

    这是arraylist的实现。可以将它用作强类型类的基(显然不是通过继承,而是通过codygray答案中表示的组合),但如果不需要类型安全性,它比集合类要好得多。

    Option Explicit
    
    Private mavInternalArray() As Variant
    Private mlArraySize As Long
    Private mlCount As Long
    Private mlGrowSize As Long
    Private mfZeroIndex As Boolean
    
    '---------------------------------------------------------------------------------------
    ' Procedure Clear
    '---------------------------------------------------------------------------------------
    Public Sub Clear()
              Dim index As Long
    
            For index = 0 To mlCount - 1
                If IsObject(mavInternalArray(index)) Then
                    Set mavInternalArray(index) = Nothing
                End If
            Next index
            mlCount = 0
    
    End Sub
    
    
    
    '---------------------------------------------------------------------------------------
    ' Procedure Swap
    '---------------------------------------------------------------------------------------
    Public Sub Swap(Index1 As Long, index2 As Long)
              Dim vTmp As Variant
    
    
            If IsObject(mavInternalArray(index2)) Then
                Set vTmp = mavInternalArray(index2)
            Else
                vTmp = mavInternalArray(index2)
            End If
    
            If IsObject(mavInternalArray(Index1)) Then
                Set mavInternalArray(index2) = mavInternalArray(Index1)
            Else
               mavInternalArray(index2) = mavInternalArray(Index1)
           End If
    
           If IsObject(vTmp) Then
               Set mavInternalArray(Index1) = vTmp
           Else
               mavInternalArray(Index1) = vTmp
           End If
    
    
    End Sub
    
    Public Property Get ZeroIndex() As Boolean
            ZeroIndex = mfZeroIndex
    End Property
    
    Public Property Let ZeroIndex(fZeroIndex As Boolean)
            mfZeroIndex = fZeroIndex
    End Property
    
    Public Property Get GrowSize() As Long
            GrowSize = mlGrowSize
    End Property
    
    Public Property Let GrowSize(lNewSize As Long)
            Debug.Assert lNewSize > 0
            mlGrowSize = lNewSize
    End Property
    
    Private Sub Class_Initialize()
            mlGrowSize = 50
            mlArraySize = mlGrowSize
            mfZeroIndex = True
            mlCount = 0
    
    
            ReDim mavInternalArray(0 To mlGrowSize - 1)
    
    End Sub
    
    '---------------------------------------------------------------------------------------
    ' Procedure Remove
    '---------------------------------------------------------------------------------------
    Public Sub Remove(index As Long)
            Dim index2 As Long
    
    
            For index2 = index To mlCount - 2
                If IsObject(mavInternalArray(index2 + 1)) Then
                    Set mavInternalArray(index2) = mavInternalArray(index2 + 1)
                Else
                    mavInternalArray(index2) = mavInternalArray(index2 + 1)
                End If
            Next index2
              If mlCount <= 0 Then
                Exit Sub
              End If
            mlCount = mlCount - 1
            If IsObject(mavInternalArray(mlCount)) Then
               Set mavInternalArray(mlCount) = Nothing
           Else
               mavInternalArray(mlCount) = False
           End If
    End Sub
    
    '---------------------------------------------------------------------------------------
    ' Procedure Items
    '---------------------------------------------------------------------------------------
    Public Function Items(index As Long) As Variant
            If Not mfZeroIndex Then
                index = index - 1
            End If
    
            If index < mlCount And index >= 0 Then
                If IsObject(mavInternalArray(index)) Then
                    Set Items = mavInternalArray(index)
                Else
                    Items = mavInternalArray(index)
                End If
           End If
    End Function
    
    Public Sub SetItem(index As Long, Item As Variant)
            If Not mfZeroIndex Then
                index = index - 1
            End If
            If IsObject(Item) Then
                Set mavInternalArray(index) = Item
            Else
                mavInternalArray(index) = Item
            End If
    End Sub
    
    '---------------------------------------------------------------------------------------
    ' Procedure Add
    '---------------------------------------------------------------------------------------
    Public Function Add(vItem As Variant) As Long
    
            mlCount = mlCount + 1
            If mlCount > mlArraySize Then
                mlArraySize = mlArraySize + mlGrowSize
                ReDim Preserve mavInternalArray(0 To mlArraySize - 1)
            End If
    
            If IsObject(vItem) Then
                Set mavInternalArray(mlCount - 1) = vItem
            Else
                mavInternalArray(mlCount - 1) = vItem
           End If
    
           Add = mlCount - 1
    
    End Function
    
    '---------------------------------------------------------------------------------------
    ' Procedure ItemArray
    '---------------------------------------------------------------------------------------
    Public Function ItemArray() As Variant
            Dim vReturnArray As Variant
    
            vReturnArray = mavInternalArray
            ReDim Preserve vReturnArray(0 To mlCount - 1)
            ItemArray = vReturnArray
    End Function
    
    Public Function Count() As Long
            Count = mlCount
    End Function
    
    
    '---------------------------------------------------------------------------------------
    ' Procedure Insert
    '---------------------------------------------------------------------------------------
    Public Function Insert(index As Long, vItem As Variant) As Long
            Dim index2 As Long
    
            'Make sure array is large enough for a new item
            mlCount = mlCount + 1
            If mlCount > mlArraySize Then
                mlArraySize = mlArraySize + mlGrowSize
                ReDim Preserve mavInternalArray(0 To mlArraySize - 1)
            End If
    
            'Bump all the items with a higher index up one spot
    
            If index >= mlCount - 1 Then
                If IsObject(vItem) Then
                    Set mavInternalArray(mlCount - 1) = vItem
                Else
                   mavInternalArray(mlCount - 1) = vItem
               End If
           Else
    
               For index2 = mlCount - 1 To index + 1 Step -1
                   If IsObject(vItem) Then
                       Set mavInternalArray(index2) = mavInternalArray(index2 - 1)
                   Else
                       mavInternalArray(index2) = mavInternalArray(index2 - 1)
                   End If
               Next index2
    
               If IsObject(vItem) Then
                   Set mavInternalArray(index) = vItem
               Else
                   mavInternalArray(index) = vItem
               End If
           End If
           Insert = mlCount - 1
    
    End Function
    
    
    Public Sub Clone(ByRef cDestinationDynamicArray As clsDynamicArray)
            Dim index As Long
    
            If cDestinationDynamicArray Is Nothing Then
                Set cDestinationDynamicArray = New clsDynamicArray
            End If
    
            cDestinationDynamicArray.Clear
    
            For index = 0 To mlCount - 1
                Call cDestinationDynamicArray.Add(mavInternalArray(index))
            Next index
    
    End Sub
    
    Public Property Get NewEnum() As IUnknown
        ''#Provides support for enumeration using For Each
        Set NewEnum = m_Customers.[_NewEnum]
    End Property
    
        3
  •  2
  •   Doc Brown    13 年前

    编辑:如果Cody Gray的解决方案对您的需求来说太过庞大,您可以尝试“穷人列表”解决方案,如下所示:

     Dim l() as somefixedclass
     Redim l(0)
    
     '...
     'increase size dynamically:
     Redim Preserve l(ubound(l)+1)
     '...
    

    当然,A List<somefixedclass> (C)或A List(Of somefixedclass) 在vb.net中更“用户友好”,因为它有查找、删除、添加范围和其他一些有用的方法。旧的vb6结构处理“空列表”情况非常糟糕。别忘了,对于大列表(大小为1000),List<..>Increasement的性能要好得多。

        4
  •  1
  •   ThiefMaster    13 年前

    vb6是一种古老的语言。它不包含现代语言(C++、C语言、Java)中的模板类型。因此,您必须将对象作为变量存储在集合中,然后在稍后将其转换回对象类型。