Разница между for (;;) и while (true) в C #? - PullRequest
17 голосов
/ 28 июля 2010

Синтаксически я вижу, что они зацикливаются до тех пор, пока не будет достигнут оператор break, но скомпилированы ли они в одно и то же? Это немного быстрее, потому что нет условия для проверки? Помимо читабельности кода, есть ли разница?

Ответы [ 7 ]

36 голосов
/ 28 июля 2010

С учетом этого ввода:

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

Удивительно, я бы сказал (идентично, даже).

21 голосов
/ 28 июля 2010

В современных компиляторах абсолютно ничего.

Исторически, однако, for(;;) был реализован как один прыжок, в то время как while(true) также имел проверку на true.

Я предпочитаю while(true), так как это делает более понятным, что я делаю.

2 голосов
/ 28 июля 2010

Я не проверял выходной код, но не должно быть никакой разницы. Любой достойный компилятор выполнит достаточно простую оптимизацию цикла, чтобы увидеть, что условие является константным выражением, и, следовательно, не требует проверки каждой итерации.

Если один из них быстрее другого, авторам компилятора C # нужно что-то им «объяснять» ...

1 голос
/ 28 июля 2010

Если бы я мог, я бы посоветовал вам взглянуть на несколько иной вопрос.Если вы используете это достаточно часто, чтобы заботиться, вы, вероятно, плохо структурируете свой код.В то время как есть вещи вроде встроенных систем, которые действительно работают вечно, циклы в большинстве нормальных программ этого не делают.Запись цикла, который утверждает, что работает вечно, обычно означает, что вы скрыли условие выхода для цикла где-то внутри, с некоторым другим потоком управления (например, if (whatever) break;) как real выход из цикла.

Этого можно и обычно следует избегать.Хотя бывают ситуации, когда операторы break имеют смысл, они, как правило, должны обрабатывать необычные ситуации, а не писать цикл, который говорит одно, а делает другое (т. Е. Говорит «выполняется вечно», но на самом деле «выполняется до тех пор, пока условие не будет выполнено»).встретились ").

0 голосов
/ 28 июля 2010

Как уже упоминалось, с любым современным компилятором это не должно иметь абсолютно никакого значения.

Я провел краткий тест на своем компьютере, рассчитав пару операций, используя одну или другую, и они всегда занимали примерно одно и то же время. Конечно, из-за запуска других процессов эти тесты не являются точными на 100%, но если есть разница в скорости (не должно быть), то это микроскопический.

0 голосов
/ 28 июля 2010

Отладочная сборка соответствует параметру 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;
            }
        }
    }

Проверка метода ExecuteFor в Reflector.

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.");
}
0 голосов
/ 28 июля 2010

Они компилируются в одно и то же.Вы можете написать тестовое приложение, которое реализует оба метода, а затем использовать ILDASM, чтобы подтвердить, что они идентичны.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...