簡體   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