TL;DR:
Is there any way to pass a class collection/list to a library sorting algorithm, and get it to return a sorted list (preferably by a named/default class property)?
I've recently been learning some Python, and was impressed by the Sorted()
function, which can sort any iterable. For numbers this is straightforward, for classes however, it is possible to assign a comparison method like this. The method tells comparison operators how to compare 2 instances of the class. Amongst other things it allows you to use builtin sorting algorithms to sort a collection of the class.
In VBA I've been half successful in mimicking this. By setting a class' default member Attribute
, you can use comparison operators (<
,=
,>=
, etc.) on classes directly. Take the example class:
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
END
Attribute VB_Name = "defaultProp"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Private randVal As Single
Public Property Get DefaultValue() As Single
Attribute Value.VB_UserMemId = 0
DefaultValue = randVal
End Property
Private Property Let DefaultValue(ByVal value As Single)
randVal = value
End Property
Private Sub Class_Initialize()
DefaultValue = Rnd()
End Sub
Two instances of this class can be compared:
Dim instance1 As New defaultProp
Dim instance2 As New defaultProp
Debug.Print instance1.DefaultValue > instance2.DefaultValue
Debug.Print instance1 > instance2 'exactly equivalent, as the DefaultValue has the correct Attribute
And if I was implementing a VBA sort algorithm that can sort values, there should be no problem sorting classes by default value*. However I would prefer to use a builtin/library sorting algorithm (for the same reasons anyone would; clarity, efficiency, proper error handling etc.)
*One of these algorithms would work for that, although must be modified to switch the entire class round, not the value of it (by adding Set
s)
Since VBA comparison operators have no issue, I assumed the same would be true for whatever the library was using. However when I tried with an ArrayList:
Sub testArrayList()
Dim arr As Object
Set arr = CreateObject("System.Collections.ArrayList")
' Initialise the ArrayList, for instance by generating random values
Dim i As Long
Dim v As defaultProp
For i = 1 To 5
Set v = New defaultProp
arr.Add v 'no problem here
Next i
arr.Sort 'raises an error
End Sub
I get an error
Failed to compare two elements in the array
So what's going on? Is it a flaw in my approach - is the default attribute not making it to the ArrayList
? Or maybe the comparison operator in whatever language the library is written in is not as floopy-gloopy as the ones VBA and Python use? Any suggestions on more builtin sorting algorithms to try would be useful too!