繁体   English   中英

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

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

我怎样才能使这个IL_ABC goto语句进入while循环呢? 如果不可能的话,我能否解释一下为什么禁止它,以及对性能相同的修改提出建议? 非常感谢!!!

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

“如果不可能的话,我可以解释为什么它被禁止吗”

忽略代码的问题(其他现有的答案解决),我将尝试提供原因的解释。 这是C#语言规范的引文

如果当前函数成员中不存在具有给定名称的标签,或者goto语句不在标签范围内,则会发生编译时错误。 该规则允许使用goto语句将控制权移出嵌套范围,但不能移入嵌套范围。

在执行到您的GOTO语句时,您的标签已经超出范围,并且不再有效。 您可以通过在while循环中声明一个整数并尝试在catch块中对其进行访问来进行测试。

不要使用goto

相反,您可以这样编写代码:

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

在内部块范围内直接使用GOTO对开发人员来说很方便,但这对编译器编写者来说是一个很大的麻烦。 问题在于,在进入任何块的范围时,您的程序都应该在后台做某些事情。 就像在进入try-catch块时一样,它应该在堆栈上创建一个特殊的框架,在进入常规块时,它应该分配所有作用域局部变量,在进入for循环体时,它应该执行其初始化程序,依此类推。 如果您只是在嵌套块内的某个随机点处跳转,那么所有这些内容都将被绕过,并且程序将简单地崩溃。 从理论上讲,编译器可以在处理GOTO跳转时针对所有可能的情况解决并提交这些内容,但是实际上,在C#编译器中创建此类功能所花费的工作量不值得您拥有它。 因此,在C#中仅禁用了进入嵌套内部范围的GOTO,并且所有块都必须具有单个入口点,这是该块的左开口括号。 在您的特定情况下,您只需要将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