我怎么能让这个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;
}
}
}
}
答案 0 :(得分:4)
"如果不可能,我可以解释为什么禁止它"
忽略代码的问题(其他现有的答案地址)我试图解释为什么。以下是C# Language Specifications
的引用如果当前函数成员中不存在具有给定名称的标签,或者如果goto语句不在标签的范围内,则会发生编译时错误。此规则允许使用goto语句将控制权移出嵌套作用域,但不能转移到嵌套作用域中。
当执行到您的GOTO声明时,您的标签已超出范围且不再有效。您可以通过在while循环中声明一个整数并尝试在catch块中访问它来测试它。
答案 1 :(得分:2)
请勿使用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);
}
}
答案 2 :(得分:0)
在内部块范围内直接使用GOTO对开发人员来说很方便,但这对编译器编写者来说是一个很大的麻烦。问题在于,在进入任何块的范围时,您的程序都应该在后台做某些事情。就像在进入try-catch块时一样,它应该在堆栈上创建一个特殊的框架,在进入常规块时,它应该分配所有作用域局部变量,在进入for循环体时,它应该执行其初始化程序,依此类推。如果您只是在嵌套块内的某个随机点处跳转,那么所有这些内容都将被绕过,并且程序将简单地崩溃。从理论上讲,编译器可以在处理GOTO跳转时针对所有可能的情况解决并提交这些内容,但是实际上,在C#编译器中创建此类功能所花费的工作量不值得您拥有它。因此,在C#中仅禁用了进入嵌套内部范围的GOTO,并且所有块都必须具有单个入口点,这是该块的左开口括号。 在您的特定情况下,您只需将IL_ASM标签移到try-catch块之外(就在'try'关键字之前),它将起作用,但是更合适的方法是使用以下构造:
bool repeat = true;
while (repeat)
{
try
{
... do something...
repeat = false;
}
catch
{
}
}