Appending an element to the end of an array is slightly involved as it requires first testing if the array is Nothing, then if not, testing if it is empty and finally invoking the ReDim statement with or without Preserve (specifying Preserve in all cases won't hurt). Having to do this in one of my applications hundreds of times for arrays having elements of a variety of types, most of them home-grown Structure types, would make the availability of a library function very desirable. The ArrayAppend method shown below solves the problem for arrays with specific element types, integer in this case, but how could ArrayAppend be phrased for arrays with elements of a general type? I tried to pass the argument " _ar() as Object ", but no luck. Perhaps I have gone overboard with the code I am submitting, but I felt it ought to be complete enough to compile and am prepared to stand corrected.
Option Strict On
Option Explicit On
Public Class CUtils
Public Shared Function ArrayAppend(ByVal _ar() As Integer,
ByVal _element As Integer) As Integer()
'
If Not _ar Is Nothing Then
Dim Len As Integer = _ar.Length
If Len = 0 Then
ReDim _ar(0)
_ar(0) = _element
Else
ReDim Preserve _ar(Len)
_ar(_ar.Length - 1) = _element
End If
Else
ReDim _ar(0)
_ar(0) = _element
End If
Return _ar
'
End Function ' ArrayAppend
'
Public Shared Sub ArrayShow(ByVal _ar() As Integer)
'
If Not _ar Is Nothing Then
For Each item As Integer In _ar
If item = _ar.Last Then
Console.Write(item & vbCrLf)
Else
Console.Write(item & " ,")
End If
Next
Else
Console.WriteLine("Nothing")
End If
'
End Sub ' ArrayShow
'
End Class ' CUtils
Option Strict On
Option Explicit On
Module MyApp
Sub Main()
Dim arInt() As Integer = Nothing
Console.WriteLine("1. Appending to a Nothing array of integers:")
CUtils.ArrayShow(arInt)
arInt = CUtils.ArrayAppend(arInt, 987)
CUtils.ArrayShow(arInt)
Console.WriteLine("2. Appending to an existing non-empty array of integers:")
arInt = {1, 2, 3}
CUtils.ArrayShow(arInt)
arInt = CUtils.ArrayAppend(arInt, 987)
CUtils.ArrayShow(arInt)
Console.WriteLine("3. Appending to an existing empty array of integers:")
arInt = {}
CUtils.ArrayShow(arInt)
arInt = CUtils.ArrayAppend(arInt, 987)
CUtils.ArrayShow(arInt)
End Sub
End Module ' MyApp
CodePudding user response:
This is exactly what generics are for. You have presumably used a generic class like List(Of T)
before, where you get to specify what T
is at run time. You can also write a generic method without it being in a generic class. In this case, you can do that and then fix the type of the parameters at run time. I would also recommend that you write it as an extension method, so you can then call it on an array instance as though it were an instance method:
Imports System.Runtime.CompilerServices
Public Module ArrayExtensions
<Extension>
Public Sub Append(Of T)(ByRef source As T(), element As T)
'If source is Nothing then new upper bound is zero.
'Otherwise, new upper bound is current Length, i.e. current upper bound 1.
Dim upperBound = If(source?.Length, 0)
ReDim Preserve source(upperBound)
source(upperBound) = element
End Sub
End Module
Sample usage:
Dim strings As String() = Nothing
Dim integers As Integer() = Nothing
strings.Append("Hello")
integers.Append(123)
Console.WriteLine("strings: " & String.Join(", ", strings))
Console.WriteLine("integers: " & String.Join(", ", integers))
strings.Append("World")
integers.Append(456)
Console.WriteLine("strings: " & String.Join(", ", strings))
Console.WriteLine("integers: " & String.Join(", ", integers))
Output:
strings: Hello integers: 123 strings: Hello, World integers: 123, 456
Because that method is generic - the (Of T)
is what makes it generic - you can call it with any type you like, as long as the array and the new value you pass are the same type, because they are both declared as type T
in the parameters.
The fact that the array parameter is declared ByRef
means that any changes you make to that parameter will be reflected in the calling code. That means that the array you called the method on will be replaced with the new array you're creating in the method.
Because this is an extension method, calling it on Nothing
will not throw a NullReferenceException
. This:
strings.Append("Hello")
is just syntactic sugar and what's really happening is this:
Append(strings, "Hello")