vb6 等价于 list<someclass>

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4177708/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-11 01:34:20  来源:igfitidea点击:

vb6 equivalent to list<someclass>

listvb6

提问by magallanes

I want to know if exist a equivalent of (.net)

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

list<somefixedclass> 

in vb6

在 vb6 中

I know that exist collection in vb6 but it uses object (variant) instead of a specific object.

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

thanks.

谢谢。

回答by Cody Gray

There is no direct equivalent in VB 6 to the generic List<T>found in VB.NET. However, there is such a thing as a Collectionin VB 6, which provides similar functionality. The primary difference is that a VB 6 Collectionis not strongly-typed, which means that all objects are stored as Variantsin the collection. In some cases, this can be beneficial, because it allows you to store many different types of data in the same collection, and in fact, VB uses this object internally. It's easy enough to use a Collectionand up-cast objects as they are retrieved from the class, but there's little you can do. It's not possible to implement strongly-typed collections in the VB runtime.

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

That being said, there is a workaround you can implement. Similarly to how collections were implemented in early versions of VB.NET before generics were introduced, you can wrap the Collectionin a class, where the only access to the internal Collectionis through methods that you expose from this class. This design pattern is commonly referred to as a "custom collection".

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

This does have the benefit of automatically handling casting, and alleviates the consumers of your code from having to remember to mind implementation details like this. It takes care of the (all too likely) possibility that you'll be looping through a collection at run-time that is only supposed to contain one type of object, but accidentally had a second, incompatible type of object added that causes your code to throw an exception. Of course, the disadvantage is that you have to re-implement most of the functionality already provided by the Collectionobject yourself, in the form of public methods on your custom collection.

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

Here's an example of how you might go about that:

以下是您可能如何处理的示例:

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

Note that in order to set the custom collection's Itemproperty as the collection's default method (like the built-in Collectionobject), you need to follow these steps in the VB 6 IDE:

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

  1. From the "Tools" menu, click "Procedure Attributes"

  2. Select the name of your custom class from the "Name" combo box.

  3. When the dialog appears, click the "Advanced" button.

  4. Select the "(Default)" item in the "Procedure ID" combo box.

  5. Click "OK"

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

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

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

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

  5. 点击“确定”


If you'd also like to allow enumeration of your custom class using the For Eachsyntax (also like the built-in Collectionobject), you can add a NewEnumfunction to your custom class:


如果您还想允许使用For Each语法(也类似于内置Collection对象)枚举您的自定义类,您可以NewEnum向您的自定义类添加一个函数:

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

Once you've done that, you need to instruct VB to use this property:

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

  1. As before, open the "Procedure Attributes" dialog from the "Tools" menu

  2. Select the name of your custom class from the "Name" combo box.

  3. When the dialog appears, click the "Advanced" button.

  4. Type the number "-4" in the "Procedure ID" combo box.

  5. Click "OK"

  1. 和以前一样,从“工具”菜单中打开“过程属性”对话框

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

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

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

  5. 点击“确定”

回答by Kris Erickson

Here is our implementation of ArrayList. You can use it as a base (not through inheritance obviously but through composition as expressed in CodyGray's answer) for a strongly typed class, but if you don't need type safety it is much better than the Collection class.

这是我们对 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

回答by ThiefMaster

VB6 is an ancient language. It doesn't contain template-like types as there are in modern languages (C++, C#, Java). So you will have to store your objects as Variants in the collection and then cast them back to your object type later.

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

回答by Doc Brown

EDIT: if Cody Gray's solution is too oversized for your needs, you might try instead the "poor man's list" solution, as follows:

编辑:如果 Cody Gray 的解决方案对于您的需求来说太大了,您可以尝试改为“穷人名单”解决方案,如下所示:

 Dim l() as somefixedclass
 Redim l(0)

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

Of course, a List<somefixedclass>(in C#) or a List(Of somefixedclass)in VB.NET is much more "user-friendly" because it has methods like Find, Remove, AddRange and some other helpful things. The old VB6 construct deals very badly with the "empty list" case. Not to forget, List<..> increasement has much better performance for big lists (size>1000).

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

回答by Don

Dictionary is the best way to contain any object.

字典是包含任何对象的最佳方式。