Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I avoid code duplication in C# while and do-while loops?

Tags:

I have a loop inside a C# method that has the following structure.

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

alternately, with a while loop:

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

But both methods use redundant code: the do-while has both an if statement and while loop checking the same condition; the while loop calls getUserInput() both before and inside the loop.

Is there a simple, non-redundant, non-ad hoc way to do what these method patterns do, either generally or in C# specifically, that only involves writing each basic component once?

like image 242
Jacob Archambault Avatar asked Jan 26 '20 00:01

Jacob Archambault


2 Answers

Assuming that getUserInput(..) can be converted into a expression yielding a boolean value*..

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

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

Other variations (presumed without non-local state) shown in comments.

*Trivially, it can always be written as a wrapping function - see Local Functions, introduced in C#7. (There are other methods for the same effect, some of which I consider 'too clever'.)

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

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

This can be followed to pushing out the logic further, in some cases. The general premise holds: getUserInput() is always invoked prior to the next 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();
}
like image 109
user2864740 Avatar answered Sep 30 '22 20:09

user2864740


do
{
     getUserInput();

     if (!inputIsBad) break;

     doSomethingElse();

} while (true);
like image 36
Kahou Avatar answered Sep 30 '22 19:09

Kahou