简体   繁体   English

新手C#-如何在while循环中制作goto语句?

[英]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? 我怎样才能使这个IL_ABC goto语句进入while循环呢? 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 这是C#语言规范的引文

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. 如果当前函数成员中不存在具有给定名称的标签,或者goto语句不在标签范围内,则会发生编译时错误。 This rule permits the use of a goto statement to transfer control out of a nested scope, but not into a nested scope. 该规则允许使用goto语句将控制权移出嵌套范围,但不能移入嵌套范围。

By the time execution has gotten to your GOTO statement, your label has fallen out of scope and is no longer valid. 在执行到您的GOTO语句时,您的标签已经超出范围,并且不再有效。 You can test this by declaring an integer in your while loop and trying to access it in catch block. 您可以通过在while循环中声明一个整数并尝试在catch块中对其进行访问来进行测试。

don't use goto 不要使用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. 在内部块范围内直接使用GOTO对开发人员来说很方便,但这对编译器编写者来说是一个很大的麻烦。 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. 就像在进入try-catch块时一样,它应该在堆栈上创建一个特殊的框架,在进入常规块时,它应该分配所有作用域局部变量,在进入for循环体时,它应该执行其初始化程序,依此类推。 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. 从理论上讲,编译器可以在处理GOTO跳转时针对所有可能的情况解决并提交这些内容,但是实际上,在C#编译器中创建此类功能所花费的工作量不值得您拥有它。 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. 因此,在C#中仅禁用了进入嵌套内部范围的GOTO,并且所有块都必须具有单个入口点,这是该块的左开口括号。 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: 在您的特定情况下,您只需要将IL_ASM标签移动到try-catch块之外(就在'try'关键字之前),它将起作用,但更合适的方法是使用以下构造:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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