12 Stimmen

vb6-Äquivalent zu list<someclass>

Ich möchte wissen, ob es ein Äquivalent von (.net)

list<somefixedclass> 

in vb6

Ich weiß, dass Sammlung in Vb6 existieren, aber es verwendet Objekt (Variante) anstelle eines bestimmten Objekts.

Danke.

26voto

Cody Gray Punkte 229889

Es gibt in VB 6 keine direkte Entsprechung zum generischen List<T> in VB.NET gefunden. Allerdings gibt es so etwas wie eine Collection in VB 6, das eine ähnliche Funktionalität bietet. Der Hauptunterschied besteht darin, dass ein VB 6 Collection es nicht stark typisiert was bedeutet, dass alle Objekte als Variants in der Sammlung. In einigen Fällen kann dies vorteilhaft sein, weil es Ihnen erlaubt, viele verschiedene Arten von Daten in derselben Sammlung zu speichern, und tatsächlich verwendet VB dieses Objekt intern. Es ist einfach genug, eine Collection und Up-Cast-Objekte, wenn sie von der Klasse abgerufen werden, aber es gibt wenig, was Sie tun können. Es ist nicht möglich, stark typisierte Sammlungen in der VB-Laufzeit zu implementieren.

Es gibt jedoch eine Lösung, die Sie anwenden können. Ähnlich wie Sammlungen wurden in frühen Versionen von VB.NET implementiert, bevor Generika eingeführt wurden, können Sie die Collection in einer Klasse, bei der der einzige Zugriff auf die internen Collection ist durch Methoden, die Sie von dieser Klasse aus zugänglich machen . Dieses Entwurfsmuster wird gemeinhin als "Individuelle Sammlung" .

Dies hat den Vorteil, dass das Casting automatisch abgewickelt wird und die Nutzer Ihres Codes sich nicht mehr um solche Implementierungsdetails kümmern müssen. Es verhindert die (allzu wahrscheinliche) Möglichkeit, dass Sie zur Laufzeit eine Schleife durch eine Sammlung ziehen, die nur einen Objekttyp enthalten soll, aber versehentlich einen zweiten, inkompatiblen Objekttyp hinzugefügt hat, der Ihren Code zu einer Ausnahme führt. Der Nachteil ist natürlich, dass Sie die meisten der Funktionen, die bereits von der Collection Objekt selbst zu erstellen, und zwar in Form von öffentlichen Methoden für Ihre benutzerdefinierte Sammlung.

Hier ist ein Beispiel dafür, wie Sie dabei vorgehen könnten:

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

Beachten Sie, dass für die Einstellung der benutzerdefinierten Sammlung der Item Eigenschaft als Standardmethode der Sammlung (wie die eingebaute Collection Objekt), müssen Sie diese Schritte in der VB 6 IDE ausführen:

  1. Klicken Sie im Menü "Werkzeuge" auf "Verfahrensattribute".

  2. Wählen Sie den Namen Ihrer benutzerdefinierten Klasse aus dem Kombinationsfeld "Name".

  3. Wenn der Dialog erscheint, klicken Sie auf die Schaltfläche "Erweitert".

  4. Wählen Sie die Option "(Standard)" im Kombinationsfeld "Verfahrens-ID".

  5. Klicken Sie auf "OK".

Wenn Sie auch die Aufzählung Ihrer benutzerdefinierten Klasse mit der For Each Syntax (ebenso wie die eingebaute Collection Objekt), können Sie ein NewEnum Funktion zu Ihrer benutzerdefinierten Klasse hinzufügen:

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

Sobald Sie das getan haben, müssen Sie VB anweisen, diese Eigenschaft zu verwenden:

  1. Öffnen Sie wie bisher den Dialog "Prozedur-Attribute" aus dem Menü "Werkzeuge".

  2. Wählen Sie den Namen Ihrer benutzerdefinierten Klasse aus dem Kombinationsfeld "Name".

  3. Wenn der Dialog erscheint, klicken Sie auf die Schaltfläche "Erweitert".

  4. Geben Sie die Zahl "-4" in das Kombinationsfeld "Verfahrens-ID" ein.

  5. Klicken Sie auf "OK".

7voto

Kris Erickson Punkte 32932

Hier ist unsere Implementierung von ArrayList. Sie können sie als Basis (natürlich nicht durch Vererbung, sondern durch Komposition, wie in CodyGrays Antwort beschrieben) für eine stark typisierte Klasse verwenden, aber wenn Sie keine Typsicherheit benötigen, ist sie viel besser als die Collection-Klasse.

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

2voto

ThiefMaster Punkte 297146

VB6 ist eine alte Sprache. Sie enthält keine schablonenartigen Typen, wie sie in modernen Sprachen (C++, C#, Java) vorhanden sind. Sie müssen also Ihre Objekte als Varianten in der Sammlung speichern und sie dann später in Ihren Objekttyp zurückverwandeln.

2voto

Doc Brown Punkte 19104

EDIT: Wenn die Lösung von Cody Gray für Ihre Bedürfnisse zu groß ist, können Sie stattdessen die "Arme-Leute-Liste"-Lösung wie folgt versuchen:

 Dim l() as somefixedclass
 Redim l(0)

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

Natürlich, ein List<somefixedclass> (in C#) oder eine List(Of somefixedclass) in VB.NET ist viel "benutzerfreundlicher", weil es Methoden wie Find, Remove, AddRange und einige andere hilfreiche Dinge hat. Das alte VB6-Konstrukt geht sehr schlecht mit dem Fall einer "leeren Liste" um. Nicht zu vergessen, List<..> increasement hat eine viel bessere Leistung für große Listen (Größe>1000).

0voto

Don Punkte 23

Ein Wörterbuch ist der beste Weg, um jedes Objekt zu enthalten.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X