VB Migration Partner must deal with arrays of UDTs in a special way, if the UDT requires to be initialized after creation. For example, consider the following VB6 code:
Type MyUdt
Number As Long
Name As String * 30
End Type
Dim udt As MyUdt
Dim arr() As MyUdt
Dim arr2(10) As MyUdt
Dim arr3(1 To 10) As MyUdt
Sub Init()
ReDim arr(5) As MyUdt
arr3(1).Number = 1234
End Sub
This is how the code is translated to VB.NET:
Friend Structure MyUdt
Public Number As Integer
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=30)> _
Public Name As VB6FixedString
Public Sub New(ByVal dummyArg As Boolean)
InitializeUDT()
End Sub
Public Sub InitializeUDT()
Name = New VB6FixedString(30)
End Sub
End Structure
Dim udt As New MyUdt(True)
Dim arr() As MyUdt
Dim arr2() As MyUdt = CreateArray6(Of MyUdt)(0, 10)
Dim arr3() As MyUdt = CreateArray6(Of MyUdt)(1, 10)
Sub Init()
ReDim6(arr, 0, 5)
arr3(1).Number = 1234
End Sub
Notice how the four variables are declared:
- The udt variable is instantiated through its nondefault constructor, which initializes it correctly.
- The arr variable is uninitialized and will be later initialized by means of a ReDim6 method, which detects that the MyUdt type requires initialization and behaves accordingly.
- The arr2 variable is initialized inline by calling the CreateArray6 method.
- The arr3 variable is also initialized inline by means of the CreateArray6 method; however, its lower index isn’t zero, therefore the CreateArray6 method throws an exception.
The problem with arrays of UDTs is that there is no way to implement such an array if its lower index is nonzero. You might think that you can solve this issue as you do with other array types, by means of a pragma that instructs VB Migration Partner to render the array as a VB6Array:
Dim arr3(1 To 10) As MyUdt
Unfortunately, this approach can’t work: you can’t use the VB6Array type (or the VB6ArrayNew type) to render an array of structures, because VB.NET prevents you from assigning value types in the structure. As a matter of fact, this code:
Dim arr3 As New VB6Array(Of MyUdt)(1, 10)
arr3(1).Number = 1234
causes the following compilation error:
Expression is a value and can’t be the target of an assignment.
To recap, an array of UDTs that require initialization and that has a nonzero lower index can’t be converted in a reliable manner because:
- by default, the array is initialized by a call to the CreateArray6 method,which cases a runtime error if the lower bound isn’t zero
- if you use an ArrayBounds pragma to force using the VB6Array type, then you get one compilation error for each statement that assigns value members in the structure.
The only viable solution is using an ArrayBounds ForceZero or ArrayBounds Shift pragma to force a zero lower index:
Dim arr3(1 To 10) As MyUdt
which produces the following VB.NET code:
Dim arr3() As MyUdt = CreateArray(Of MyUdt)(0, 9)
Remember to revise the code that accesses the array, to ensure that the change in lower and upper indices doesn’t cause any runtime error.