简体   繁体   中英

newbie C# - How to make a goto statement inside a while loop?

how i can make this IL_ABC goto statement going inside this while loop? If not possible, can i get a explanation why its forbidden, as well sugestions of modification in code that performs equally? Thanks so much!!!

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;

namespace test.Properties
{
    internal class Testing
    {
        public Testing()
        {
            Data.smethod_0();
        }

        [DllImport("myfile.dll")]
        public static extern bool EM(int int0, string string0);

        public static void smethod_0(object object0)
        {
            try
            {
                while (true)
                {
                IL_ABC:
                    Process[] processesByName = Process.GetProcessesByName("dummy");
                    if (processesByName.Length == 1)
                    {
                        if (Testing.EM(processesByName[0].Id, "a.dll"))
                        {
                            processesByName[0].Kill();
                            Thread.Sleep(2000);
                            continue;
                        }
                        Thread.Sleep(2000);
                        if (Testing.EM(processesByName[0].Id, "b.dll"))
                        {
                            processesByName[0].Kill();
                            Thread.Sleep(2000);
                            continue;
                        }
                    }
                    Thread.Sleep(2000);
                }
            }
            catch (Exception ex)
            {
                Debug.smethod_0("Error! " + ex.Message);
                Thread.Sleep(2000);
                goto IL_ABC;
            }
        }
    }
}

"If not possible, can i get a explanation why its forbidden"

Ignoring the issues with the code (the other existing answer addresses that) Ill try to provide an explanation as to why. Here is a quote from the C# Language Specifications

If a label with the given name does not exist in the current function member, or if the goto statement is not within the scope of the label, a compile-time error occurs. This rule permits the use of a goto statement to transfer control out of a nested scope, but not into a nested scope.

By the time execution has gotten to your GOTO statement, your label has fallen out of scope and is no longer valid. You can test this by declaring an integer in your while loop and trying to access it in catch block.

don't use goto

instead you can write your code like this :

while (true)
{
    try
    {
        Process[] processesByName = Process.GetProcessesByName("dummy");
        if (processesByName.Length == 1)
        {
            if (Testing.EM(processesByName[0].Id, "a.dll"))
            {
                processesByName[0].Kill();
                Thread.Sleep(2000);
                continue;
            }
            Thread.Sleep(2000);
            if (Testing.EM(processesByName[0].Id, "b.dll"))
            {
                processesByName[0].Kill();
                Thread.Sleep(2000);
                continue;
            }
        }
        Thread.Sleep(2000);
    }

    catch (Exception ex)
    {
        Debug.smethod_0("Error! " + ex.Message);
        Thread.Sleep(2000);
    } 
}

Direct GOTO inside the scope of inner block would be convenient for the developers, but it it as a big hassle for the compiler writers. The problem is that at the point of entering the scope of any block your program should do certain things behind the scene. Like at entering try-catch block it should create a special frame on the stack, at entering regular block it should allocate all scope local variables, at entering for-loop body it should execute its initializers and so on and so on. If you just jump at a random point inside the nested block all those things will get bypassed and your program will simply crash. It is theoretically possible to resolve and commit those things for all possible scenarios by the compiler at the point of processing your GOTO jump, but practically the amount of work spent on creating such feature in C# compiler does not worth the gain you would attain by having it. So GOTO into nested inner scopes are simply disabled in C# and all blocks have to have a single entry point, which is a left opening brace of the block. In your particular case you just have to move IL_ASM label outside the try-catch block (just before the 'try' keyword) and it will work, but more proper is to use this construction:

        bool repeat = true;
        while (repeat)
        {
            try
            {  
                ... do something...
                repeat = false;
            }
            catch
            {
            }
        }            

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM