vb6相当于list <someclass> </someclass>

时间:2010-11-14 13:40:30

标签: list vb6

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

list<somefixedclass> 

in vb6

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

感谢。

5 个答案:

答案 0 :(得分:22)

VB 6中没有与VB.NET中的通用List<T>直接等价的东西。但是,VB 6中存在Collection这样的东西,它提供了类似的功能。主要区别在于VB 6 Collection 不是强类型,这意味着所有对象都存储为集合中的Variants。在某些情况下,这可能是有益的,因为它允许您在同一个集合中存储许多不同类型的数据,事实上,VB在内部使用此对象。从类中检索它们时,使用Collection和上传对象很容易,但是你几乎无能为力。在VB运行时中无法实现强类型集合。

话虽如此,您可以实施一种解决方法。类似于在引入泛型之前如何在早期版本的VB.NET中实现集合,您可以将Collection包装在一个类中,其中对内部Collection的唯一访问是通过以下方法你从这个类中公开。此设计模式通常称为“自定义集合”

这确实有自动处理强制转换的好处,并减轻代码的使用者必须记住这样的实现细节。它会处理(很可能)您在运行时循环遍历集合的可能性,该集合只应包含一种类型的对象,但意外地添加了第二种不兼容的对象类型,导致您的代码抛出异常。当然,缺点是您必须以自定义集合上的公共方法的形式重新实现Collection对象本身提供的大部分功能。

以下是您可以采用的示例:

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属性设置为集合的默认方法(如内置Collection对象),您需要在VB 6 IDE中执行以下步骤:< / p>

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

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

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

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

  5. 点击“确定”


  6. 如果您还希望使用For Each语法(也类似于内置的Collection对象)允许枚举自定义类,则可以向自定义类添加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. 点击“确定”

答案 1 :(得分:5)

这是我们对ArrayList的实现。对于强类型类,您可以将它用作基础(不是通过显然继承,而是通过CodyGray的答案中表达的组合),但如果您不需要类型安全,则它比Collection类好得多。

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

答案 2 :(得分:2)

编辑:如果Cody Gray的解决方案太大而无法满足您的需求,您可以尝试使用“穷人列表”解决方案,如下所示:

 Dim l() as somefixedclass
 Redim l(0)

 '...
 'increase size dynamically:
 Redim Preserve l(ubound(l)+1)
 '...

当然,VB.NET中的List<somefixedclass>(在C#中)或List(Of somefixedclass)更加“用户友好”,因为它有Find,Remove,AddRange和其他一些有用的东西。 。旧的VB6构造与“空列表”案件的处理非常糟糕。不要忘记,List&lt; ..&gt;对于大型列表(大小> 1000),增加具有更好的性能。

答案 3 :(得分:1)

VB6是一种古老的语言。它不包含类似于模板的类型,就像现代语言(C ++,C#,Java)一样。因此,您必须将对象存储为集合中的变体,然后将它们转换回您的对象类型。

答案 4 :(得分:0)

词典是包含任何对象的最佳方法。