[英]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.