Skip to main content
syntax highligting
Source Link
svick
  • 24.5k
  • 4
  • 53
  • 89
Public Function ToString() As String
'Returns a string that represents the current List object.

    ToString = StringFormat("{0}<{1}>", TypeName(Me), _
                                        Coalesce(this.ItemTypeName, "Variant"))

End Function
Public Function ToString() As String
'Returns a string that represents the current List object.

    ToString = StringFormat("{0}<{1}>", TypeName(Me), _
                                        Coalesce(this.ItemTypeName, "Variant"))

End Function
Private Function ValidateItemType(value As Variant)

    If this.ItemTypeName = vbNullString Then this.ItemTypeName = TypeName(value)
    ValidateItemType = IsTypeSafe(value)

End Function
Private Function ValidateItemType(value As Variant)

    If this.ItemTypeName = vbNullString Then this.ItemTypeName = TypeName(value)
    ValidateItemType = IsTypeSafe(value)

End Function
Private Function IsReferenceType() As Boolean
    If Count = 0 Then Exit Function
    IsReferenceType = IsObject(this.Encapsulated(1))
End Function
Private Function IsReferenceType() As Boolean
    If Count = 0 Then Exit Function
    IsReferenceType = IsObject(this.Encapsulated(1))
End Function
Private Function IsReferenceType() As Boolean
    If this.ItemTypeName = vbNullString Then Exit Function
    IsReferenceType = IsObject(this.Encapsulated(1))
End Function
Private Function IsReferenceType() As Boolean
    If this.ItemTypeName = vbNullString Then Exit Function
    IsReferenceType = IsObject(this.Encapsulated(1))
End Function
Private Function IsComparable() As Boolean
    If IsReferenceType Then
        IsComparable = TypeOf First Is IComparable
    End If
End Function

Private Function IsEquatable() As Boolean
    If IsReferenceType Then
        IsEquatable = TypeOf First Is IEquatable
    End If
End Function
Private Function IsComparable() As Boolean
    If IsReferenceType Then
        IsComparable = TypeOf First Is IComparable
    End If
End Function

Private Function IsEquatable() As Boolean
    If IsReferenceType Then
        IsEquatable = TypeOf First Is IEquatable
    End If
End Function
    If isRef Then

        '...
        isSmaller = CompareReferenceTypes(Item(i), smallest) < 0
        '...

    Else

        '...
        isSmaller = CompareValueTypes(Item(i), smallest) < 0
        '...

    End If
    If isRef Then

        '...
        isSmaller = CompareReferenceTypes(Item(i), smallest) < 0
        '...

    Else

        '...
        isSmaller = CompareValueTypes(Item(i), smallest) < 0
        '...

    End If
Public Property Get NewEnum() As IUnknown
Attribute NewEnum.VB_UserMemId = -4
Attribute NewEnum.VB_MemberFlags = "40"
'Gets an enumerator that iterates through the List.

    Set NewEnum = this.Encapsulated.[_NewEnum]

End Property
Public Property Get NewEnum() As IUnknown
Attribute NewEnum.VB_UserMemId = -4
Attribute NewEnum.VB_MemberFlags = "40"
'Gets an enumerator that iterates through the List.

    Set NewEnum = this.Encapsulated.[_NewEnum]

End Property
For Each value In values
    Add value
Next
For Each value In values
    Add value
Next
Public Sub Add(ParamArray values())
'Adds the specified element(s) to the end of the List.

    Dim valuesArray() As Variant
    valuesArray = values

    AddArray valuesArray

End Sub

Public Sub AddRange(values As List)
'Adds the specified elements to the end of the List.

    AddArray values.ToArray

End Sub

Public Sub AddArray(values() As Variant)
'Adds the specified elements to the end of the List.

    Dim value As Variant, i As Long
    For i = LBound(values) To UBound(values)
        If ValidateItemType(value) Then 
            this.Encapsulated.Add values(i)
        Else
            RaiseErrorUnsafeType "AddArray()", TypeName(value)
        End If
    Next

End Sub
Public Sub Add(ParamArray values())
'Adds the specified element(s) to the end of the List.

    Dim valuesArray() As Variant
    valuesArray = values

    AddArray valuesArray

End Sub

Public Sub AddRange(values As List)
'Adds the specified elements to the end of the List.

    AddArray values.ToArray

End Sub

Public Sub AddArray(values() As Variant)
'Adds the specified elements to the end of the List.

    Dim value As Variant, i As Long
    For i = LBound(values) To UBound(values)
        If ValidateItemType(value) Then 
            this.Encapsulated.Add values(i)
        Else
            RaiseErrorUnsafeType "AddArray()", TypeName(value)
        End If
    Next

End Sub
Public Sub Insert(ByVal Index As Long, ParamArray values())
'Inserts the specified element(s) into the List at the specified index.

    Dim valuesArray() As Variant
    valuesArray = values

    InsertArray Index, valuesArray

End Sub
Public Sub Insert(ByVal Index As Long, ParamArray values())
'Inserts the specified element(s) into the List at the specified index.

    Dim valuesArray() As Variant
    valuesArray = values

    InsertArray Index, valuesArray

End Sub
Public Function IsSortable() As Boolean
'Determines whether the List can be sorted.

    If Count = 0 Then RaiseErrorListContainsNoElement "IsSortable()"
    If IsReferenceType Then
        
        IsSortable = IsComparable

    Else

        IsSortable = IsNumeric(First) _
                Or IsDate(First) _
                Or this.ItemTypeName = "String"

   End If

End Function
Public Function IsSortable() As Boolean
'Determines whether the List can be sorted.

    If Count = 0 Then RaiseErrorListContainsNoElement "IsSortable()"
    If IsReferenceType Then
        
        IsSortable = IsComparable

    Else

        IsSortable = IsNumeric(First) _
                Or IsDate(First) _
                Or this.ItemTypeName = "String"

   End If

End Function
Public Function ToString() As String
'Returns a string that represents the current List object.

    ToString = StringFormat("{0}<{1}>", TypeName(Me), _
                                        Coalesce(this.ItemTypeName, "Variant"))

End Function
Private Function ValidateItemType(value As Variant)

    If this.ItemTypeName = vbNullString Then this.ItemTypeName = TypeName(value)
    ValidateItemType = IsTypeSafe(value)

End Function
Private Function IsReferenceType() As Boolean
    If Count = 0 Then Exit Function
    IsReferenceType = IsObject(this.Encapsulated(1))
End Function
Private Function IsReferenceType() As Boolean
    If this.ItemTypeName = vbNullString Then Exit Function
    IsReferenceType = IsObject(this.Encapsulated(1))
End Function
Private Function IsComparable() As Boolean
    If IsReferenceType Then
        IsComparable = TypeOf First Is IComparable
    End If
End Function

Private Function IsEquatable() As Boolean
    If IsReferenceType Then
        IsEquatable = TypeOf First Is IEquatable
    End If
End Function
    If isRef Then

        '...
        isSmaller = CompareReferenceTypes(Item(i), smallest) < 0
        '...

    Else

        '...
        isSmaller = CompareValueTypes(Item(i), smallest) < 0
        '...

    End If
Public Property Get NewEnum() As IUnknown
Attribute NewEnum.VB_UserMemId = -4
Attribute NewEnum.VB_MemberFlags = "40"
'Gets an enumerator that iterates through the List.

    Set NewEnum = this.Encapsulated.[_NewEnum]

End Property
For Each value In values
    Add value
Next
Public Sub Add(ParamArray values())
'Adds the specified element(s) to the end of the List.

    Dim valuesArray() As Variant
    valuesArray = values

    AddArray valuesArray

End Sub

Public Sub AddRange(values As List)
'Adds the specified elements to the end of the List.

    AddArray values.ToArray

End Sub

Public Sub AddArray(values() As Variant)
'Adds the specified elements to the end of the List.

    Dim value As Variant, i As Long
    For i = LBound(values) To UBound(values)
        If ValidateItemType(value) Then 
            this.Encapsulated.Add values(i)
        Else
            RaiseErrorUnsafeType "AddArray()", TypeName(value)
        End If
    Next

End Sub
Public Sub Insert(ByVal Index As Long, ParamArray values())
'Inserts the specified element(s) into the List at the specified index.

    Dim valuesArray() As Variant
    valuesArray = values

    InsertArray Index, valuesArray

End Sub
Public Function IsSortable() As Boolean
'Determines whether the List can be sorted.

    If Count = 0 Then RaiseErrorListContainsNoElement "IsSortable()"
    If IsReferenceType Then
        
        IsSortable = IsComparable

    Else

        IsSortable = IsNumeric(First) _
                Or IsDate(First) _
                Or this.ItemTypeName = "String"

   End If

End Function
Public Function ToString() As String
'Returns a string that represents the current List object.

    ToString = StringFormat("{0}<{1}>", TypeName(Me), _
                                        Coalesce(this.ItemTypeName, "Variant"))

End Function
Private Function ValidateItemType(value As Variant)

    If this.ItemTypeName = vbNullString Then this.ItemTypeName = TypeName(value)
    ValidateItemType = IsTypeSafe(value)

End Function
Private Function IsReferenceType() As Boolean
    If Count = 0 Then Exit Function
    IsReferenceType = IsObject(this.Encapsulated(1))
End Function
Private Function IsReferenceType() As Boolean
    If this.ItemTypeName = vbNullString Then Exit Function
    IsReferenceType = IsObject(this.Encapsulated(1))
End Function
Private Function IsComparable() As Boolean
    If IsReferenceType Then
        IsComparable = TypeOf First Is IComparable
    End If
End Function

Private Function IsEquatable() As Boolean
    If IsReferenceType Then
        IsEquatable = TypeOf First Is IEquatable
    End If
End Function
    If isRef Then

        '...
        isSmaller = CompareReferenceTypes(Item(i), smallest) < 0
        '...

    Else

        '...
        isSmaller = CompareValueTypes(Item(i), smallest) < 0
        '...

    End If
Public Property Get NewEnum() As IUnknown
Attribute NewEnum.VB_UserMemId = -4
Attribute NewEnum.VB_MemberFlags = "40"
'Gets an enumerator that iterates through the List.

    Set NewEnum = this.Encapsulated.[_NewEnum]

End Property
For Each value In values
    Add value
Next
Public Sub Add(ParamArray values())
'Adds the specified element(s) to the end of the List.

    Dim valuesArray() As Variant
    valuesArray = values

    AddArray valuesArray

End Sub

Public Sub AddRange(values As List)
'Adds the specified elements to the end of the List.

    AddArray values.ToArray

End Sub

Public Sub AddArray(values() As Variant)
'Adds the specified elements to the end of the List.

    Dim value As Variant, i As Long
    For i = LBound(values) To UBound(values)
        If ValidateItemType(value) Then 
            this.Encapsulated.Add values(i)
        Else
            RaiseErrorUnsafeType "AddArray()", TypeName(value)
        End If
    Next

End Sub
Public Sub Insert(ByVal Index As Long, ParamArray values())
'Inserts the specified element(s) into the List at the specified index.

    Dim valuesArray() As Variant
    valuesArray = values

    InsertArray Index, valuesArray

End Sub
Public Function IsSortable() As Boolean
'Determines whether the List can be sorted.

    If Count = 0 Then RaiseErrorListContainsNoElement "IsSortable()"
    If IsReferenceType Then
        
        IsSortable = IsComparable

    Else

        IsSortable = IsNumeric(First) _
                Or IsDate(First) _
                Or this.ItemTypeName = "String"

   End If

End Function
added 4 characters in body
Source Link
Mathieu Guindon
  • 75.6k
  • 18
  • 195
  • 469

It is assumed that only valuereference types can implement IComparable and IEquatable, and that is correct in VB6. Therefore, the presence of CompareValueTypes and EquateValueTypes functions is somewhat awkward, but their usage makes a quite enjoyable reading:

It is assumed that only value types can implement IComparable and IEquatable, and that is correct in VB6. Therefore, the presence of CompareValueTypes and EquateValueTypes functions is somewhat awkward, but their usage makes a quite enjoyable reading:

It is assumed that only reference types can implement IComparable and IEquatable, and that is correct in VB6. Therefore, the presence of CompareValueTypes and EquateValueTypes functions is somewhat awkward, but their usage makes a quite enjoyable reading:

Source Link
Mathieu Guindon
  • 75.6k
  • 18
  • 195
  • 469

Public Function ToString() As String
'Returns a string that represents the current List object.

    ToString = StringFormat("{0}<{1}>", TypeName(Me), _
                                        Coalesce(this.ItemTypeName, "Variant"))

End Function

This means the string representation of this List is "List<Variant>" when this.ItemTypeName is empty or vbNullString.

This function should be somewhere at the very top:

Private Function ValidateItemType(value As Variant)

    If this.ItemTypeName = vbNullString Then this.ItemTypeName = TypeName(value)
    ValidateItemType = IsTypeSafe(value)

End Function

This is where the string representation of the List stops being "List<Variant>" and becomes List<T>


Given this information, there's a flaw in the IsReferenceType function, which might return the wrong result if the list originally contained objects and then was emptied so that Count = 0:

Private Function IsReferenceType() As Boolean
    If Count = 0 Then Exit Function
    IsReferenceType = IsObject(this.Encapsulated(1))
End Function

The correct code should be:

Private Function IsReferenceType() As Boolean
    If this.ItemTypeName = vbNullString Then Exit Function
    IsReferenceType = IsObject(this.Encapsulated(1))
End Function

In these snippets:

Private Function IsComparable() As Boolean
    If IsReferenceType Then
        IsComparable = TypeOf First Is IComparable
    End If
End Function

Private Function IsEquatable() As Boolean
    If IsReferenceType Then
        IsEquatable = TypeOf First Is IEquatable
    End If
End Function

It is assumed that only value types can implement IComparable and IEquatable, and that is correct in VB6. Therefore, the presence of CompareValueTypes and EquateValueTypes functions is somewhat awkward, but their usage makes a quite enjoyable reading:

    If isRef Then

        '...
        isSmaller = CompareReferenceTypes(Item(i), smallest) < 0
        '...

    Else

        '...
        isSmaller = CompareValueTypes(Item(i), smallest) < 0
        '...

    End If

The Attribute Item.VB_UserMemId = 0 setting in the getter for the Item property makes that getter the type's default property, making Item(i) also be accessible with Me(i). Cool stuff. Even better:

Public Property Get NewEnum() As IUnknown
Attribute NewEnum.VB_UserMemId = -4
Attribute NewEnum.VB_MemberFlags = "40"
'Gets an enumerator that iterates through the List.

    Set NewEnum = this.Encapsulated.[_NewEnum]

End Property

Attribute NewEnum.VB_UserMemId = -4 instructs VB to use this method in For Each loop constructs; this enables AddRange(values As List) to do what it does:

For Each value In values
    Add value
Next

Given AddArray(values() As Variant), I think AddValues(ParamArray values()) could easily replace Add(value As Variant) - if there's only 1 value to add, both methods can be used and that makes it an ambiguous API. Add, AddRange and AddArray should be rewritten as follows:

Public Sub Add(ParamArray values())
'Adds the specified element(s) to the end of the List.

    Dim valuesArray() As Variant
    valuesArray = values

    AddArray valuesArray

End Sub

Public Sub AddRange(values As List)
'Adds the specified elements to the end of the List.

    AddArray values.ToArray

End Sub

Public Sub AddArray(values() As Variant)
'Adds the specified elements to the end of the List.

    Dim value As Variant, i As Long
    For i = LBound(values) To UBound(values)
        If ValidateItemType(value) Then 
            this.Encapsulated.Add values(i)
        Else
            RaiseErrorUnsafeType "AddArray()", TypeName(value)
        End If
    Next

End Sub

If Count = 0 Then Exit Function, wherever it's used, is an opportunity for some RaiseErrorListContainsNoElement, instead of returning an empty Variant or a meaningless False value.


Insert(ByVal Index As Long, value As Variant) and InsertValues(ByVal Index As Long, ParamArray values()) have exactly the same issue as Add and AddValues have; InsertValues should disappear and be replaced with this:

Public Sub Insert(ByVal Index As Long, ParamArray values())
'Inserts the specified element(s) into the List at the specified index.

    Dim valuesArray() As Variant
    valuesArray = values

    InsertArray Index, valuesArray

End Sub

The conditions for IsSortable are somewhat redundant and the firstItem variable only hides intent - accessing the first item isn't expensive enough to take this readability hit (besides this isn't called in a loop), so IsSortable() could be rewritten like this, and again If Count = 0 Then Exit Function is an opportunity for some RaiseErrorListContainsNoElement:

Public Function IsSortable() As Boolean
'Determines whether the List can be sorted.

    If Count = 0 Then RaiseErrorListContainsNoElement "IsSortable()"
    If IsReferenceType Then
        
        IsSortable = IsComparable

    Else

        IsSortable = IsNumeric(First) _
                Or IsDate(First) _
                Or this.ItemTypeName = "String"

   End If

End Function

IsTypeSafe is interesting. It works, but it's a little too stiff and a bit more effort could be put into accepting Long values within Integer range in a List<Integer>, and so on.


Remove(ParamArray values()) is already consistent with the changes made to Add and Insert, however RemoveRange breaks the naming convention established with AddRange and InsertRange which both take a List as a parameter. Since RemoveRange should keep its .net List<T> meaning, AddRange and InsertRange should be renamed AddList and InsertList, which would be consistent with AddArray and InsertArray.


That's all I can see.