Подтвердить что ты не робот

Разница между for (;;) и while (true) в С#?

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

4b9b3361

Ответ 1

Учитывая этот ввод:

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

Замечательно похоже, я бы сказал (идентичный, даже).

Ответ 2

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

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

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

Ответ 3

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

Если кто-то быстрее, чем другой, разработчикам компилятора С# нужно что-то "для них"...

Ответ 4

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

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

Ответ 5

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

Ответ 6

Отладочная сборка соответствует до (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 в рефлекторе.

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.");
}

Ответ 7

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

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