HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

UniqueList Class in VBA

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
classuniquelistvba

Problem

I often find myself abusing dictionary objects just for the exist method like this,

For Each x in Something
    If Not dict.Exists(x) Then dict.Add x, False 
Next x


Then just exploit the .Exists(x) method. It happens often enough that I thought it merited it's own class.

Instead of composing Scripting.Dictionary, I decided to just maintain a sorted list of unique items. Usage is simple; unique items are inserted into the collection sorted. Non-unique items are not added.

Attributes

Let's just get this out of the way. Attribute VB_PredeclaredId must be set to True and NewEnum allows the class to be iterable. I still haven't found a way to replicate this using an array instead of a collection. With an array I could offload some of my code to my standard library, but then this wouldn't be standalone or portable.

VERSION 1.0 CLASS
BEGIN
  MultiUse = -1
END
Attribute VB_Name = "UniqueList"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False

Option Explicit

Private list As Collection

Public Sub Class_Initialize()
    Set list = New Collection
End Sub
Public sub Class_Terminate()
    Set list = Nothing
End Sub
Public Property Get NewEnum() As IUnknown
Attribute NewEnum.VB_UserMemId = -4

    Set NewEnum = list.[_NewEnum]

End Property


Data Manipulation

```
Public Sub Add(ByVal element As Variant)

If IsEmpty Then

list.Add element
Exit Sub

End If

Dim index As Long
index = LocateIndex(element)

If (list(index) > element) Then
list.Add element, Before:=index
ElseIf list(index) < element Then
list.Add element, After:=index
End If

End Sub
Public Sub Merge(ByVal list_ As Variant)

Dim element As Variant
For Each element In list_
Add element
Next element

End Sub
Public Sub Remove(ByVal element As Variant)

Dim index As Long
index = LocateIndex(element)

If (list(in

Solution

Just a couple of notes. The biggest of which is that I think you've misunderstood what VB_PredeclaredId does. It creates a default instance of the class. Which allows you to do things like this

UniqueList.Add someItem


Without declaring and setting a new instance of the class. It's a cool feature, but it's not what allows the list to be iterable and you don't need it here. The [_NewEnum] is what allows the For Each syntax.

The Clear method doesn't need to Set list = Nothing. Drop that line and just set it to a new instance of Collection.

Lastly, I find it really odd that you have a list with no way to get an element back out of the list. We can add and remove items, but not retrieve them. I would rethink implementing an Item method.

Code Snippets

UniqueList.Add someItem

Context

StackExchange Code Review Q#60831, answer score: 4

Revisions (0)

No revisions yet.