Различие между для (; ;) и, в то время как (верный) в C#?

Синтаксически я вижу, что они циклично выполняются неограниченно долго, пока оператор завершения не достигнут, но они компилируются в то же самое? Для немного быстрее, потому что это не имеет условия проверить? Кроме удобочитаемости кода, существует ли даже различие?

17
задан Corey Ogburn 27 July 2010 в 20:03
поделиться

7 ответов

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

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

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

36
ответ дан 30 November 2019 в 10:18
поделиться

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

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

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

21
ответ дан 30 November 2019 в 10:18
поделиться

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

0
ответ дан 30 November 2019 в 10:18
поделиться

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

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

0
ответ дан 30 November 2019 в 10:18
поделиться

Отладочная сборка соответствует while(true). Используйте reflector и вы сможете увидеть результаты.

    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
ответ дан 30 November 2019 в 10:18
поделиться

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

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

2
ответ дан 30 November 2019 в 10:18
поделиться

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

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

1
ответ дан 30 November 2019 в 10:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: