"for (bool flag = true; flag; flag = false) {...}" - это нормально? - PullRequest
4 голосов
/ 15 февраля 2012

Я никогда не видел цикл for, инициализированный таким образом, и не понимаю, почему он будет написан таким образом?

Я провожу некоторые исследования по подключению к серверу IMAP в .NETи начал искать код из библиотеки с именем ImapX .Я нашел цикл for в методе, который записывает данные в NetworkStream, а затем, кажется, читает ответ в цикле for в стиле фанк.Я не хочу дословно копировать и вставлять чужой код, но вот суть:

public bool SendData(string data)
{
  try
  {
    this.imapStreamWriter.Write(data);

    for (bool flag = true; flag; flag = false)
    {
      var s = this.imapStreamReader.ReadLine();
    }
  }
  catch (Exception)
  {
    return false;
  }

  return true;
}

Опять же, это не точный код, но это общая идея.Это все, что делает метод, он не использует ответ сервера, он просто возвращает true, если не было выдано исключение.Я просто не понимаю, как или почему цикл for используется таким образом;Может кто-нибудь объяснить, какие преимущества инициализации этого предложения, если таковые имеются?

Ответы [ 4 ]

5 голосов
/ 15 февраля 2012

Это ужасный способ выполнить цикл один раз. Если вы измените flag инициализатор на что-то, что не всегда true, у него может быть немного больше смысла, но не много. Я совершенно безоговорочно предложил этот код до сих пор:

Animal animal = ...;
for (Dog dog = animal as Dog; dog != null; dog = null)
{
    // Use dog...
}

... как способ использования оператора as без "загрязнения" внешней области видимости. Но это глупость языка, а не то, что я когда-либо действительно использовал бы.

2 голосов
/ 16 февраля 2012

Ранее я предполагал, что вы смотрите на исходный код, но из ваших комментариев это звучит так, как будто вы смотрите на восстановленный C # Reflector, основанный на MSIL.Важно понимать, что это не обязательно имеет близкое сходство с исходным кодом, как написано.

На уровне MSIL не существует такой вещи, как цикл for или цикл while.Есть только условные инструкции ветки.(См. Здесь: http://weblogs.asp.net/kennykerr/archive/2004/09/23/introduction-to-msil-part-6-common-language-constructs.aspx) Любой инструмент, пытающийся воссоздать C #, должен сделать несколько предположений о том, как изначально был структурирован код.Кажется вероятным, что это изначально не было записано как цикл for, но что Reflector обнаружил, что IL мог быть сгенерирован циклом for, и его эвристика сделала неверное предположение, что ондолжен быть цикл for, а не что-то еще.

Если я посмотрю на тот же код в ILSpy, он будет отображен как цикл while.Это все еще избыточно, но выглядит намного менее странно.Более того, возможно, что исходный код действительно что-то оптимизировал, например, вызовы методов [Conditional] или кода, помеченного директивами #if.С другой стороны, возможно, оригинальный код, используемый для чего-то другого, но части были закомментированы - комментарии не хранятся в IL.Или, может быть, в прошлом было больше кода, и он был просто удален.

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

1 голос
/ 15 февраля 2012

У меня было это как комментарий, но я полагаю, что это тоже ответ.

"Цикл" бессмыслен.Он инициализирует flag до true и объявляется для выполнения только тогда, когда flag все еще true.Однако flag явно устанавливается на false после первой итерации.Так что в этом случае он гарантированно будет запускаться один и только один раз.

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

0 голосов
/ 15 февраля 2012

Цикл for в значительной степени запрещен, как отмечали другие.

Однако он делает одну вещь, которая может иметь или не иметь значение: он вводит область имен пространства .Область действия переменной s - это тело цикла for.s выходит из области действия после выхода из цикла for.Вы можете получить тот же эффект, просто создав блок, таким образом:

{
  var s = this.imapStreamReader.ReadLine();
}

Что все еще довольно глупо.

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

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