Как избежать дублирования кода в C# циклах while и do-while? - PullRequest
4 голосов
/ 26 января 2020

У меня есть oop внутри C# метода, который имеет следующую структуру.

do
{
     getUserInput();
     if (inputIsBad)
     {
          doSomethingElse();
     } 
} while (inputIsBad);

поочередно, с временем l oop:

getUserInput();
while (inputIsBad)
{
     doSomethingElse();
     getUserInput();
}

Но оба метода используют избыточный код: у do-while есть и оператор if, и пока l oop проверяет одно и то же условие; в то время как l oop вызывает getUserInput () как до, так и внутри l oop.

Существует ли простой, не избыточный, не ad ho c способ сделать то, что делают эти шаблоны методов, вообще или в C# конкретно, который включает только написание каждый базовый c компонент один раз?

Ответы [ 4 ]

1 голос
/ 27 января 2020
do
{
     getUserInput();

     if (!inputIsBad) break;

     doSomethingElse();

} while (true);
1 голос
/ 26 января 2020

Предполагая, что getUserInput(..) может быть преобразовано в выражение с логическим значением * ..

while (getUserInput()
    && isBadInput()) {
  doSomethingElse();
}

// Prompts for user input, returns false on a user-abort (^C)
private bool getUserInput() { .. }

Другие варианты (предположительно без нелокального состояния), показанные в комментариях.

* Тривиально, это всегда можно записать в виде функции обтекания - см. Локальные функции , введенные в C # 7. (Существуют другие методы для того же эффекта, некоторые из которых я считаю «слишком умными».)

// local function
bool getUserInputAlwaysTrue() {
   getUserInput(); // assume void return
   return true;
}

while (getUserInputAlwaysTrue()
    && isBadInput()) {
  doSomethingElse();
}

В некоторых случаях это может сопровождаться дальнейшим выталкиванием логики c. Общая посылка гласит: getUserInput() всегда вызывается до следующего isBadInput().

// local function or member method
// Prompt for user input, returning true on bad input.
bool getCheckedUserInput() {
   getUserInput(); // assume void return
   return isBadInput();
}

while (getCheckedUserInput()) {
  doSomethingElse();
}
0 голосов
/ 31 января 2020

Опираясь на user2864740's answer:

Предположим, что getUserInput () может быть преобразован в функцию, которая возвращает true, если входные данные хорошие и плохие в противном случае. Предполагая, что его исходный тип возвращаемого значения не был логическим или пустым, верните его исходное возвращаемое значение через параметр out или ref в зависимости от случая, например,

int originalReturnValue;

while (!getUserInput(out originalReturnValue))
{
     doSomethingElse();
} 

...

bool getUserInput<T>(out T output)
{
// method body
}
0 голосов
/ 27 января 2020

Я бы использовал логическую переменную, которую нужно объявить вне тела l oop. Таким образом, вам нужно только один раз выполнить проверку inputIsBad. Я также превратил его в метод, так как это кажется более логичным.

bool badInput = true;  // Assume bad until checked -- failsafe.
do
{
  getUserInput();
  badInput = inputIsBad();
  if (badInput)
  {
    doSomethingElse();
  } 
} while (badInput);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...