VB6 supports the GoSub statement, whereas VB.NET doesn’t. The GoSub statement isn’t structured and is a symptom of poor programming, therefore we recommend that you edit the original VB6 code to replace GoSubs with calls to methods and arguments.
At any rate, in its quest to deliver VB.NET code that “just works,” VB Migration Partner is capable to correctly translate GoSub and On GoSub statements in most circumstances, by transforming them into GoTo statements and by maintaining a return address stack. For example, consider the following VB6 code:
Sub Test(ByVal first As Integer, ByVal second As Integer)
Dim index As Integer
index = first
GoSub ShowIndex
index = second
GoSub ShowIndex
Exit Sub
ShowIndex:
Debug.Print index
Return
End Sub
This is how the above code is converted to VB.NET:
Sub Test(ByVal first As Short, ByVal second As Short)
Dim _vb6ReturnStack As New System.Collections.Generic.Stack(Of Integer)
Dim index As Short = first
vb6ReturnStack.Push(1): GoTo ShowIndex
ReturnLabel_1:
Index = second
vb6ReturnStack.Push(2): GoTo ShowIndex
ReturnLabel_2:
Exit Sub
ShowIndex:
Debug.WriteLine(index)
GoTo _vb6ReturnHandler
Exit Sub
_vb6ReturnHandler:
Select Case _vb6ReturnStack.Pop()
Case 1: GoTo ReturnLabel_1
Case 2: GoTo ReturnLabel_2
End Select
End Sub
The resulting VB.NET code works flawlessly, but it’s apparent that it is neither readable nor maintainable, hence our recommendation to revise the original VB6 code and manually transforms GoSubs into method calls. If you decide to rely on VB Migration Partner for automated translation of GoSub and On GoSub statements, though, you must be aware of a minor limitation of this technique, which manifests itself when the GoSub is located inside a For or For Each loop, as in this code:
Sub Test(ByVal first As Integer, ByVal second As Integer)
Dim index As Integer
For index = first To second
GoSub ShowIndex
Next
Exit Sub
ShowIndex:
Debug.Print index
Return
End Sub
This is the converted VB.NET code:
Sub Test(ByVal first As Short, ByVal second As Short)
Dim _vb6ReturnStack As New System.Collections.Generic.Stack(Of Integer)
Dim index As Short
For index = first To second
vb6ReturnStack.Push(1): GoTo ShowIndex
ReturnLabel_1:
Next
Exit Sub
ShowIndex:
Debug.WriteLine(index)
GoTo _vb6ReturnHandler
Exit Sub
_vb6ReturnHandler:
Select Case _vb6ReturnStack.Pop()
Case 1: GoTo ReturnLabel_1
End Select
End Sub
When you compile this code, the VB.NET compiler produces the following error:
'GoTo ReturnLabel_1' is not valid because 'ReturnLabel_1' is inside
a 'For' or 'For Each' statement that does not contain this statement.
The reason is, you can’t jump into a For or For Each loop from the outside. A similar problem occurs when a GoTo statement points to a label inside a With...End With block.
Short of getting rid of the GoSub statement – which, once again, is the recommended strategy -, the only way to avoid this error is by transforming the For loop into the equivalent Do While loop. For example, the previous VB6 code might be rewritten as follows:
Sub Test(ByVal first As Integer, ByVal second As Integer)
Dim index As Integer
Index = first
Do While index <= second
GoSub ShowIndex
index = index + 1
Loop
Exit Sub
ShowIndex:
Debug.Print index
Return
End Sub
The above migrates and runs correctly under VB.NET. Similar transformations can be performed with For loops with negative steps or with For Each loops.
Similarly, if the GoSub statement is located inside a With…End With block, you have to get rid of the block and ensure that object references that start with a dot are fixed accordingly. For example, assume that you start with this VB6 code:
Sub MoveControl(ByVal ctrl As Control, dx As Integer, dy As Integer)
With ctrl
.Left = .Left + dx
GoSub DoSomething
.Top = .Top + dy
End With
...
Exit Sub
DoSomething:
...
Return
End Sub
Here’s how you should revise the code to get rid of the With…End With block before attempting to migrate it:
Sub MoveControl(ByVal ctrl As Control, dx As Integer, dy As Integer)
ctrl.Left = ctrl.Left + dx
GoSub DoSomething
ctrl.Top = ctrl.Top + dy
...
Exit Sub
DoSomething:
...
Return
End Sub