vbscriptsortedlist

Can I use System.Collections.Generic.SortedList in VBscript?


I'm trying to generate a sorted list in VBscript doing this:

Set GNDcons = CreateObject( "System.Collections.Generic.SortedList<string, integer>" )

however it doesn't work, I get Scode:800a01ad Is it even possible to use this type in VBscript? I saw there's another SortedList in System.Collections without the possibility of setting the data types but the use was deprecated.

enter image description here


Solution

  • You can use the System.Collections.SortedList type in VBScript; just avoid the System.Collections.Generic types, and constructors requiring parameters.

    Here's a simple example:

    Dim sl : Set sl = CreateObject("System.Collections.SortedList")
    sl.Capacity = 5
    sl.Add "Just", 0
    sl.Add "One", 1
    sl.Add "Of", 2
    sl.Add "Many", 3
    sl.Add "Examples", 4
    
    Dim i, k, v
    For i = 0 To sl.Count-1
        k = sl.GetKey(i)
        v = sl.Item(k)
        WScript.Echo "Item at index " & i & " contains key " & k & " and value " & v
    Next
    

    If you want to simulate type constraints for keys and values, then you can create a VBScript wrapper class. For example:

    Option Explicit
    
    Class CSortedList
        Private sl
        Private TKeyVarType
        Private TValueVarType
    
        Private Sub Class_Initialize()
            TKeyVarType = vbEmpty
            TValueVarType = vbEmpty
            Set sl = CreateObject("System.Collections.SortedList")
        End Sub
    
        Private Sub Class_Terminate()
            Set sl = Nothing
        End Sub
    
        Public Property Let TKey(ByVal VarType_)
            TKeyVarType = VarType_
        End Property
    
        Public Property Get TKey()
            TKey = TKeyVarType
        End Property
    
        Public Property Let TValue(ByVal VarType_)
            TValueVarType = VarType_
        End Property
    
        Public Property Get TValue()
            TValue = TValueVarType
        End Property
    
        Public Property Let Capacity(ByVal v_)
            sl.Capacity = v_
        End Property
    
        Public Property Get Capacity()
            Capacity = sl.Capacity
        End Property
    
        Public Property Get Count()
            Count = sl.Count
        End Property
    
        Public Property Get IsFixedSize()
            IsFixedSize = sl.IsFixedSize
        End Property
    
        Public Property Get IsReadOnly()
            IsReadOnly = sl.IsReadOnly
        End Property
    
        Public Property Get IsSynchronized()
            IsSynchronized = sl.IsSynchronized
        End Property
    
        Public Property Let Item(ByVal key, ByVal value)
            If VarType(key) <> TKeyVarType Then
                WScript.StdErr.WriteLine "Error: Wrong type for key"
            ElseIf VarType(value) <> TValueVarType Then
                WScript.StdErr.WriteLine "Error: Wrong type for value"
            Else
                sl.Item(key) = value
            End If
        End Property
    
        Public Property Get Item(ByVal key)
            If VarType(key) <> TKeyVarType Then
                WScript.StdErr.WriteLine "Error: Wrong type for key"
            ElseIf vbObject = VarType(sl.Item(key)) Then
                Set Item = sl.Item(key)
            Else
                Item = sl.Item(key)
            End If
        End Property
    
        Public Property Get Keys()
            Set Keys = sl.Keys
        End Property
    
        Public Property Get SyncRoot()
            Set SyncRoot = sl.SyncRoot
        End Property
    
        Public Property Get Values()
            Set Values = sl.Values
        End Property
    
        Public Sub Add(ByVal key, ByVal value)
            If VarType(key) <> TKeyVarType Then
                WScript.StdErr.WriteLine "Error: Wrong type for key"
            ElseIf VarType(value) <> TValueVarType Then
                WScript.StdErr.WriteLine "Error: Wrong type for value"
            Else
                sl.Add key, value
            End If
        End Sub
    
        Public Sub Clear()
            sl.Clear
        End Sub
    
        Public Function Clone()
            Set Clone = sl.Clone()
        End Function
    
        Public Function Contains(ByVal key)
            If VarType(key) <> TKeyVarType Then
                WScript.StdErr.WriteLine "Error: Wrong type for key"
            Else
                Contains = sl.Contains(key)
            End If
        End Function
    
        Public Function ContainsKey(ByVal key)
            ContainsKey = Contains(key)
        End Function
    
        Public Function ContainsValue(ByVal value)
            If VarType(value) <> TValueVarType Then
                WScript.StdErr.WriteLine "Error: Wrong type for value"
            Else
                ContainsValue = sl.ContainsValue(value)
            End If
        End Function
    
        Public Function GetByIndex(ByVal index)
            If vbObject = VarType(sl.GetByIndex(index)) Then
                Set GetByIndex = sl.GetByIndex(index)
            Else
                GetByIndex = sl.GetByIndex(index)
            End If
        End Function
    
        Public Function GetEnumerator()
            Set GetEnumerator = sl.GetEnumerator()
        End Function
    
        Public Function GetKey(ByVal index)
            If vbObject = sl.GetKey(index) Then
                Set GetKey = sl.GetKey(index)
            Else
                GetKey = sl.GetKey(index)
            End If
        End Function
    
        Public Function GetKeyList()
            Set GetKeyList = sl.GetKeyList()
        End Function
    
        Public Function GetValueList()
            Set GetValueList = sl.GetValueList()
        End Function
    
        Public Function IndexOfKey(ByVal key)
            If VarType(key) <> TKeyVarType Then
                WScript.StdErr.WriteLine "Error: Wrong type for key"
            Else
                IndexOfKey = sl.IndexOfKey(key)
            End If
        End Function
    
        Public Function IndexOfValue(ByVal value)
            If VarType(value) <> TValueVarType Then
                WScript.StdErr.WriteLine "Error: Wrong type for value"
            Else
                IndexOfValue = sl.IndexOfValue(value)
            End If
        End Function
    
        Public Sub Remove(ByVal key)
            If VarType(key) <> TKeyVarType Then
                WScript.StdErr.WriteLine "Error: Wrong type for key"
            Else
                sl.Remove key
            End If
        End Sub
    
        Public Sub RemoveAt(ByVal index)
            sl.RemoveAt index
        End Sub
    
        Public Sub SetByIndex(ByVal index, ByVal value)
            If VarType(value) <> TValueVarType Then
                WScript.StdErr.WriteLine "Error: Wrong type for value"
            Else
                sl.SetByIndex index, value
            End If
        End Sub
    
        Public Sub TrimToSize()
            sl.TrimToSize
        End Sub
    End Class
    
    With New CSortedList
        .TKey = vbString
        .TValue = vbInteger
        .Capacity = 5
        .Add "Just", 0
        .Add "One", 1
        .Add "Of", 2
        .Add "Many", 3
        .Add "Examples", 4
    
        Dim i, k, v
        For i = 0 To .Count-1
            k = .GetKey(i)
            v = .Item(k)
            WScript.Echo "Item at index " & i & " contains key " & k & " and value " & v
        Next
    End With
    

    Note: The above wrapper class has not been 100% tested, but does restrict keys to Variant string subtypes, and values to Variant integer subtypes. The resulting list is automatically sorted by keys.

    Output:

    Item at index 0 contains key Examples and value 4
    Item at index 1 contains key Just and value 0
    Item at index 2 contains key Many and value 3
    Item at index 3 contains key Of and value 2
    Item at index 4 contains key One and value 1