I have a do-while loop designed to get a number from user input in the console. I included error checking and many optional variables to make it versatile (i.e. min and max allowed values, an array of values that must contain the input, and a params variable for any specific not allowed input values).
After redesigning the loop to use some continue statements (based on design constraints), the error checking no longer seems to be working.
public static int GetNumber(int min = int.MinValue, int max = int.MaxValue, string prompt = "Number", int[] permittedNums = null, params int[] exceptions)
{
string? numString;
int num;
do
{
Console.Write($"{prompt}: ");
numString = Console.ReadLine();
ClearConsoleLine();
if (!int.TryParse(numString, out num)) { continue; }
if (permittedNums != null && !permittedNums.Contains(num)) { continue; }
} while (num < min || num > max || exceptions.Contains(num));
return num;
}
I checked to make sure that my logic was correct to make sure that at least the continue statement was hit, and as far as I could tell it should have worked, but it was allowing the input to go through without running the loop again.
I already tried looking at other questions but I couldn't find an answer.
continue
actually is simple goto
, and in loops it works like this:
do {
...
continue;
...
} while (condition)
is equivalent to:
do {
...
goto LABEL;
...
LABEL:
} while (condition)
so, even after continue condition is still evaluated (or in case of for
loop - counter is increased and so on).
you have multiple options, for example you can put all your continuation conditions in while's condition (it works because of short circuit evaluation):
do
{
Console.Write($"{prompt}: ");
numString = Console.ReadLine();
} while (
!int.TryParse(numString, out num) ||
(permittedNums != null && !permittedNums.Contains(num)) ||
num < min ||
num > max ||
exceptions.Contains(num)
);
return num;
but it is hard to read and modify, I'd prefer to see something like this:
while (true)
{
Console.Write($"{prompt}: ");
var numString = Console.ReadLine();
int num;
if (!int.TryParse(numString, out num)) { continue; }
if (permittedNums != null && !permittedNums.Contains(num)) { continue; }
if (num < min || num > max || exceptions.Contains(num)) { continue; }
return num;
}
so, every time you have failed check - you skip return
and start loop from the beginning