CodeConverter icon indicating copy to clipboard operation
CodeConverter copied to clipboard

VB -> C#: OnErrorGoToStatementSyntax and OnErrorResumeNextStatementSyntax

Open GrahamTheCoder opened this issue 5 years ago • 7 comments

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

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

GrahamTheCoder avatar Nov 15 '19 13:11 GrahamTheCoder

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 image

valeriu33 avatar Mar 05 '20 08:03 valeriu33

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.

GrahamTheCoder avatar Mar 05 '20 19:03 GrahamTheCoder

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

GrahamTheCoder avatar Jul 05 '21 20:07 GrahamTheCoder

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;
        }
    }

GrahamTheCoder avatar Jul 05 '21 21:07 GrahamTheCoder

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

GrahamTheCoder avatar Feb 14 '22 21:02 GrahamTheCoder

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
            }
        }
    }
}

GrahamTheCoder avatar Aug 10 '23 21:08 GrahamTheCoder

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

qoselahali77 avatar Oct 05 '23 23:10 qoselahali77