VB10 vs VB6: Array Lower Bounds
This is part of series of posts categorized under VB10 vs VB6.
“Arrays may not have a lower bound other than zero.”
This, as it turns out, is absolutely true; however, with a twist. Although VB10 does not allow the “native” array type (the one defined by the language), there are a ton of ways that this can be handled. I would also argue that the multitude of ways that are available would also provide a solution that better suites the needs for circumstances where having a different lower bound is desired.
Let’s see how you could accomplish similar functionality without delving into the .NET Framework. The most direct solution is to handle the lower bound yourself by determining the offset from 0 and access the array accordingly.
1
2
3
4
Dim lbound As Integer = 10
Dim ubound As Integer = 20
Dim a(ubound - lbound) As Integer
a(10 - lbound) = value
So you could easily handle this by utilizing some simple math. Let’s say, however, that you’d like to have it programatically similar to VB6. You could create a class that abstracts this math and provides a very similar experience to VB6.
1
2
Dim a As New VbIntegerArray(lbound, ubound)
a(10) = value
The code for the VbIntegerArray
is as follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Public Class VbIntegerArray
Private m_lbound As Integer
Private m_int() As Integer
Public Sub New(ByVal lowerBound As Integer, ByVal upperBound As Integer)
Me.ReDim(lowerBound, upperBound)
End Sub
Public Sub [ReDim](ByVal lowerBound As Integer, ByVal upperBound As Integer)
m_lbound = lowerBound
ReDim m_int(upperBound - lowerBound + 1)
End Sub
Default Public Property Item(ByVal index As Integer) As Integer
Get
Return m_int(index - m_lbound)
End Get
Set(ByVal Value As Integer)
m_int(index - m_lbound) = Value
End Set
End Property
End Class
Not too difficult. Note, this code is based off of a blog entry by Phil Weber. I made a few minor changes to, so feel free to use this or his depending on your needs. Using this method requires that you create a separate class for each variable type you want to have an “array” with a different lower bounds than 0. Another approach, as mentioned toward the end of Phil’s blog entry is the possibility of using Generics
. I’ve re-wired the above class to create a generic version. The internal implementation is not a ‘native’ language array, but instead is leveraging the Generic List
object. Because of this, I am having to pre-populate the “array” with items so that the indexer works as expected. Furthermore, because it is a generic type, I’m populating each entry with Nothing
(NULL
). Outside of that, everything is basically similar to the direct implementation.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Public Class VbArrayGeneric(Of T)
Private m_lbound As Integer
Private m_array As List(Of T)
Public Sub New(ByVal lowerBound As Integer, ByVal upperBound As Integer)
Me.ReDim(lowerBound, upperBound)
End Sub
Public Sub [ReDim](ByVal lowerBound As Integer, ByVal upperBound As Integer)
m_lbound = lowerBound
m_array.Clear()
For index As Integer = 0 To upperBound - lowerBound
m_array.Add(Nothing)
Next
End Sub
Default Public Property Item(ByVal index As Integer) As T
Get
Return m_array(index - m_lbound)
End Get
Set(ByVal Value As T)
m_array(index - m_lbound) = Value
End Set
End Property
End Class
To utilize the above code, you can do the following:
1
2
3
4
5
6
7
8
9
Dim a As New VbArrayGeneric(Of Integer)(10, 20)
For index As Integer = 10 To 20
a(index) = index
Next
For index As Integer = 10 To 20
Console.WriteLine(a(index))
Next
In addition to the ways described, the Generic
version of the Dictionary
class might also be leveraged to provide similar capabilities. By using a dictionary, you would no longer be bound (no pun intended) to a lower and upper bound since each entry has a unique key and can be of any value. If interested in seeing this approach, please let me know.
Verdict
This one’s hard to provide a clear verdict. On the one hand, it’s clear that the ‘native’ language array does not support arrays with a lower bound other than 0. On the other, there are a plethora of ways to implement “arrays” available in VB10. Because of this, I’m going to call this one a wash. (Note: I may come back and give this one to VB6 depending on how the rest of the list goes; only because of the way that the entry was stated, VB10 does not do exactly what it states.)
Update(s)
Bill McCarthy (MVP) writes in : “I’d add IEnumerable
/IEnumerable(Of T)
support to the classes passing it straight through to the array’s GetEnumerator
. And this is actually where it gets interesting. If I recall correctly For Each with arrays in .NET is optimized; you’d probably lose a little bit with the custom class, but as long as it was IEnumerable(Of T)
as opposed to the non-generic version there shouldn’t be any boxing overhead. That said, I seem to recall (but don’t quote me on this as it is a LONG time ago), that VB6 had performance problems with For Each
(pCode versus native may have changed the outcome too), as I think it went all variant gooey stuff ;) Anyway, real world implementation in .NET, include IEnumerable(Of T)
.