从语法上来说,我看到它们无限循环,直到达到break语句,但它们是否编译为同一个东西?因为它没有条件可以检查吗?除了代码可读性之外,还有差异吗?
答案 0 :(得分:36)
鉴于此输入:
private static void ForLoop()
{
int n = 0;
for (; ; )
{
Console.WriteLine(n++);
}
}
private static void WhileLoop()
{
int n = 0;
while (true)
{
Console.WriteLine(n++);
}
}
...你得到这个输出:
.method private hidebysig static void ForLoop() cil managed
{
// Code size 14 (0xe)
.maxstack 3
.locals init ([0] int32 n)
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: ldloc.0
IL_0003: dup
IL_0004: ldc.i4.1
IL_0005: add
IL_0006: stloc.0
IL_0007: call void [mscorlib]System.Console::WriteLine(int32)
IL_000c: br.s IL_0002
} // end of method Program::ForLoop
.method private hidebysig static void WhileLoop() cil managed
{
// Code size 14 (0xe)
.maxstack 3
.locals init ([0] int32 n)
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: ldloc.0
IL_0003: dup
IL_0004: ldc.i4.1
IL_0005: add
IL_0006: stloc.0
IL_0007: call void [mscorlib]System.Console::WriteLine(int32)
IL_000c: br.s IL_0002
} // end of method Program::WhileLoop
非常相似,我会说(相同,甚至)。
答案 1 :(得分:21)
在现代编译器中,绝对没有。
但是,从历史上看,for(;;)
实现为单跳,而while(true)
也检查为true。
我更喜欢while(true)
,因为它让我更清楚我在做什么。
答案 2 :(得分:2)
我没有检查输出代码,但应该没有任何区别。任何体面的编译器都会做足够简单的循环优化,看看条件是一个常量表达式,因此不需要检查每次迭代。
如果一个比另一个快,那么C#编译器编写者需要向他们发出一些东西......
答案 3 :(得分:1)
如果可以的话,我建议你看一个有点不同的问题。如果您经常使用这些中的任何一个,那么您可能很难构建代码。虽然嵌入式系统确实可以永远运行,但大多数普通代码中的循环都没有。编写一个声明永远运行的循环通常意味着你已经隐藏了内部某处循环的退出条件,其他一些控制流(例如,if (whatever) break;
)就像真实一样退出循环。
这可以而且通常应该避免。虽然有些情况下break
语句有意义,但它们通常应该处理不寻常的情况,而不是写一个循环说一件事而是另一件事(即说“永远跑”,但确实“直到满足条件“)。
答案 4 :(得分:0)
他们编译成同样的东西。您可以编写一个实现两种方法的测试应用程序,然后使用ILDASM确认它们的IL是相同的。
答案 5 :(得分:0)
调试程序集符合while(true)。使用反射器,您可以看到结果。
static void Main(string[] args)
{
ExecuteWhile();
ExecuteFor();
}
private static void ExecuteFor()
{
for (; ; )
{
Console.WriteLine("for");
string val = Console.ReadLine();
if (string.IsNullOrEmpty(val))
{
Console.WriteLine("Exit for.");
break;
}
}
}
private static void ExecuteWhile()
{
while (true)
{
Console.WriteLine("while");
string val = Console.ReadLine();
if (string.IsNullOrEmpty(val))
{
Console.WriteLine("Exit while.");
break;
}
}
}
检查Reflector中的ExecuteFor
方法。
private static void ExecuteFor()
{
while (true)
{
Console.WriteLine("for");
if (string.IsNullOrEmpty(Console.ReadLine()))
{
Console.WriteLine("Exit for.");
return;
}
}
}
同一代码的优化版本会为ExecuteFor
private static void ExecuteFor()
{
do
{
Console.WriteLine("for");
}
while (!string.IsNullOrEmpty(Console.ReadLine()));
Console.WriteLine("Exit for.");
}
对于详细程度,这里是优化的ExecuteWhile
...
private static void ExecuteWhile()
{
do
{
Console.WriteLine("while");
}
while (!string.IsNullOrEmpty(Console.ReadLine()));
Console.WriteLine("Exit while.");
}
答案 6 :(得分:0)
正如其他人所提到的,对于任何现代编译器,它应该完全没有区别。
我在我的计算机上做了一个简短的测试,使用其中一个进行了几次操作,并且它们总是花费大约相同的时间。当然,由于其他过程正在运行,这些测试并非100%准确,但如果速度存在差异(不应该存在),那么它就是微观测试。