从循环外跳入循环内的标签不是非法的C#代码吗?
Isn't it illegal C# code to jump into a label inside a loop from outside the loop?
在第 9 频道 this video 的大约 09:19 处,Jeffrey Richter 向 Charlie Calvert 演示了他的 AsyncEnumerator
,他展示了一段代码,其中控制流跳转到while
循环内的标签服从循环外的 goto
指令。那让我震惊。我一时间难以置信。
所以,我尝试了类似的方法,正如我所料,C# 不允许我这样做,因为标签不在我想跳转的 goto
语句的块范围内。
using System;
namespace JumpToInsideALoopWithGoToTest
{
class Program
{
static int i = 0;
static int someRandomNumber = 0;
static void Main(string[] args)
{
Console.WriteLine("\nPress any key to continue...");
Console.ReadKey();
}
static bool GoToInsideLoopTest(int howMany)
{
if (i == 0)
{
i = 1; return true;
}
if (i == 1)
{
while (someRandomNumber < howMany)
{
i = 2;
return true;
Increment: i++;
}
}
if (i == 2)
{
goto Increment;
}
return false;
}
}
}
然后呢?我什至不知道我的问题是什么。比如,我当时看到了什么?
我怀疑他展示的代码是伪代码?或者这样的事情在 IL 中是可能的吗?无论如何,那是什么?
也许他在演示 C# 编译器为异步和迭代器方法生成的状态机。编译器不需要遵守 C# 语法要求。它需要做的就是让 CLR 满意。
可以说,在 CLR 级别,所有局部变量都在函数的顶部声明。它们随处可见。没有声明问题,也没有未初始化变量的问题。
CLR 提出了自己的要求,主要是关于正确形成执行堆栈的要求。当跳转到堆栈为空的位置(例如语句之间)时,这不是问题。由于 await
可以出现在表达式中,因此有一个重写可以重新连接所有内容,以便状态机跳转到具有空堆栈的位置。
对于 C# 编译器来说,跳转到几乎任何地方都不是问题。
在第 9 频道 this video 的大约 09:19 处,Jeffrey Richter 向 Charlie Calvert 演示了他的 AsyncEnumerator
,他展示了一段代码,其中控制流跳转到while
循环内的标签服从循环外的 goto
指令。那让我震惊。我一时间难以置信。
所以,我尝试了类似的方法,正如我所料,C# 不允许我这样做,因为标签不在我想跳转的 goto
语句的块范围内。
using System;
namespace JumpToInsideALoopWithGoToTest
{
class Program
{
static int i = 0;
static int someRandomNumber = 0;
static void Main(string[] args)
{
Console.WriteLine("\nPress any key to continue...");
Console.ReadKey();
}
static bool GoToInsideLoopTest(int howMany)
{
if (i == 0)
{
i = 1; return true;
}
if (i == 1)
{
while (someRandomNumber < howMany)
{
i = 2;
return true;
Increment: i++;
}
}
if (i == 2)
{
goto Increment;
}
return false;
}
}
}
然后呢?我什至不知道我的问题是什么。比如,我当时看到了什么?
我怀疑他展示的代码是伪代码?或者这样的事情在 IL 中是可能的吗?无论如何,那是什么?
也许他在演示 C# 编译器为异步和迭代器方法生成的状态机。编译器不需要遵守 C# 语法要求。它需要做的就是让 CLR 满意。
可以说,在 CLR 级别,所有局部变量都在函数的顶部声明。它们随处可见。没有声明问题,也没有未初始化变量的问题。
CLR 提出了自己的要求,主要是关于正确形成执行堆栈的要求。当跳转到堆栈为空的位置(例如语句之间)时,这不是问题。由于 await
可以出现在表达式中,因此有一个重写可以重新连接所有内容,以便状态机跳转到具有空堆栈的位置。
对于 C# 编译器来说,跳转到几乎任何地方都不是问题。