CodeConverter
CodeConverter copied to clipboard
VB -> C#: OnErrorGoToStatementSyntax and OnErrorResumeNextStatementSyntax
2023-12-10: Yet to find an acceptable general way to handle this since they're all way too messy. Still happy to take specific common examples that could be easily handled
-
OnErrorGoToStatementSyntax
,OnErrorResumeNextStatementSyntax
- Many cases can probably be reasonably successfully converted as
try...catch
and then a goto within the catch and an appropriately placed label
- Many cases can probably be reasonably successfully converted as
Resume Next Example
int lineNumber = 1;
try
{
line1: lineNumber++;
//First line of code would be here
line2: lineNumber++;
//Second line of code would be here
}
catch
{
switch(lineNumber)
{
case 1: goto line1;
case 2: goto line2;
}
}
Note: Even this messy solution isn't valid because line1 is out of scope of the catch block and could be in a nested scope even within the try block
I found this issue as well, my project has a lot of "On Error GoTo"s and I'd be grateful if someone implemented this syntax
On Error Goto is hard enough to convert cleanly into a try catch.
The "Resume Next" is even more problematic since it forces the code to resume from the next line. Things I've considered:
- Wrapping every single line in a try catch
- Using a counter variable to track which line was reached
- Encasing every statement in a lambda
Perhaps the generated IL will give some further ideas, please post any ideas that come to mind here.
The neatest solution I've thought of for Resume Next
is:
for (int lineNumber = 1; lineNumber <= 2; lineNumber++)
{
try
{
switch(lineNumber)
{
case 1:
//First line of code would be here
break;
case 2:
//Second line of code would be here
break;
}
}
catch
{
}
}
Or equivalently (if auto-formatting allows it):
for (int lineNumber = 1; lineNumber <= 2; lineNumber++) try
{
switch(lineNumber)
{
case 1:
//First line of code would be here
break;
case 2:
//Second line of code would be here
break;
}
}
catch
{
}
We'd need to pull up any variable declarations to the outer scope for this to work
Actually this would save us having to mess around with variable scopes EDIT: sadly the switch has to be at the start of the try block, and a loop is required because the labels are out of scope otherwise
int lineNumber = 1;
try
{
line1: lineNumber++;
//First line of code would be here
line2: lineNumber++;
//Second line of code would be here
}
catch
{
switch(lineNumber)
{
case 1: goto line1;
case 2: goto line2;
}
}
One thing that could be done in all cases, is to convert the code inside the block and place an error compiler directive showing the original code. That way it's quicker to fix manually EDIT: Now done
One idea for implementing exactly the resume next logic:
static void Main(string[] args)
{
Wrap(() =>
{
Console.WriteLine("First line");
});
int result = default;
Wrap(() =>
{
result = Divide(10, 0); // Division by zero to simulate an error not directly in the method at hand that therefore shouldn't be supressed
});
Wrap(() =>
{
Console.WriteLine("Third line " + result);
});
}
// Not sure if line number will help, but something like this to be able to match the stack trace's top frame
static void Wrap(Action action, [CallerLineNumber] int lineNumber = 0)
{
try
{
action.Invoke();
}
catch (Exception ex)
{
if (IsDirectlyWithinLambda(ex, lineNumber))
{
// Handle or suppress the exception
Console.WriteLine($"Exception suppressed at line {lineNumber}: {ex.Message}");
}
else
{
throw; // Rethrow if not directly within the lambda
}
}
}
}
Private Sub Button9_Click(sender As Object, e As EventArgs) Handles Button9.Click 'show all COM Ports ComboBox5.Items.Clear() For Each sp As String In My.Computer.Ports.SerialPortNames ComboBox5.Items.Add(sp) Next