VB6 эквивалент списка <someclass> - PullRequest
10 голосов
/ 14 ноября 2010

Я хочу знать, существует ли эквивалент (.net)

list<somefixedclass> 

в vb6

Я знаю, что существует коллекция в vb6, но она использует объект (вариант) вместо определенного объекта.

спасибо.

Ответы [ 4 ]

22 голосов
/ 14 ноября 2010

В VB 6 нет прямого эквивалента универсальному List<T>, найденному в VB.NET. Однако в 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) необходимо выполнить следующие действия в среде IDE VB 6:

  1. В меню «Инструменты» нажмите «Атрибуты процедуры»

  2. Выберите имя вашего пользовательского класса в поле со списком «Имя».

  3. Когда появится диалоговое окно, нажмите кнопку «Дополнительно».

  4. Выберите пункт «(По умолчанию)» в поле со списком «Идентификатор процедуры».

  5. Нажмите "ОК"


Если вы также хотите разрешить перечисление своего пользовательского класса с использованием синтаксиса 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. Введите число «-4» в поле со списком «ИД процедуры».

  5. Нажмите «ОК»

5 голосов
/ 15 ноября 2010

Вот наша реализация 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 голосов
/ 14 ноября 2010

РЕДАКТИРОВАТЬ: если решение Cody Grey слишком велико для ваших нужд, вместо этого вы можете попробовать решение «Список бедняков» следующим образом:

 Dim l() as somefixedclass
 Redim l(0)

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

Конечно, List<somefixedclass> (в C #) или List(Of somefixedclass) в VB.NET гораздо более «дружественный», поскольку в нем есть такие методы, как Find, Remove, AddRange и некоторые другие полезные.Старая конструкция VB6 очень плохо справляется со случаем «пустого списка».Не стоит забывать, что увеличение списка <..> намного лучше для больших списков (размер> 1000).

1 голос
/ 14 ноября 2010

VB6 - древний язык.Он не содержит шаблоноподобных типов, как в современных языках (C ++, C #, Java).Таким образом, вам нужно будет сохранить ваши объекты как варианты в коллекции, а затем снова привести их к типу объекта.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...