HiveBrain v1.2.0
Get Started
← Back to all entries
debugcsharpMinor

Handling exceptions and executing code if one was found

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
handlingexecutingexceptionscodeonewasfoundand

Problem

I have this code:

try
{
    Console.WriteLine("Input number {0}", i + 1);
    int number = ReadNumber(start, end);
}
catch (Exception ex)
{
    if (ex is ArgumentException)
    {
        Console.WriteLine("The input number wasn't in the alowed range. Please try again.");
    }
    else if (ex is FormatException)
    {
        Console.WriteLine("The input isn't an integer number. Please try again.");
    }
    else
    {
        Console.WriteLine("An unknown error occured. Please try again.");
    }

    i--;
}


I am wondering if there is a better way to do this - catch all exceptions and handle them and then, if any exception was caught, I want to reduce i by 1.

Solution

So I'm assuming that all of this code is in a for loop, and that for loop is incrementing i as it's loop statement.

What you can do here is not unconditionally increment i in each iteration of the loop, and instead only increment i if you're able to read in the number successfully:

for (int i = 0; i < 10; )
{
    try
    {
        Console.WriteLine("Input number {0}", i + 1);
        int number = ReadNumber(start, end);
        i++;
    }
    catch (ArgumentException)
    {
        Console.WriteLine("The input number wasn't in the alowed range. Please try again.");
    }
    catch (FormatException)
    {
        Console.WriteLine("The input isn't an integer number. Please try again.");
    }
    catch (Exception)
    {
        Console.WriteLine("An unknown error occured. Please try again.");
    }
}


However, for this case I'd say that there's an option that's better still.

What you should really do is, rather than having a method try to get another value from the user and possibly failing and possibly succeeding and needing to be called again, create a method that keeps asking the user for a value until it gets a valid one. This logic is far easier to implement at that scope than it is to try to continually add more iterations to the loop.

Once you create a method that will always get a valid value, trying as hard as it needs to:

public static int ReadNumber(int start, int end, int iteration)
{
    while (true)
    {
        Console.WriteLine("Input number {0}", iteration + 1);
        int n;
        if (!int.TryParse(Console.ReadLine(), out n))
            Console.WriteLine("The input isn't an integer number. Please try again.");
        else if (n  end)
            Console.WriteLine("The input number wasn't in the alowed range. Please try again.");
        else
            return n;
    }
}


(Also note the use of conditional checks to determine if the user input is valid, rather than using exceptions for non-exceptional control flow.)

Now our loop is dead easy:

for (int i = 0; i < 10; i++)
{
    int number = ReadNumber(start, end, i);
}

Code Snippets

for (int i = 0; i < 10; )
{
    try
    {
        Console.WriteLine("Input number {0}", i + 1);
        int number = ReadNumber(start, end);
        i++;
    }
    catch (ArgumentException)
    {
        Console.WriteLine("The input number wasn't in the alowed range. Please try again.");
    }
    catch (FormatException)
    {
        Console.WriteLine("The input isn't an integer number. Please try again.");
    }
    catch (Exception)
    {
        Console.WriteLine("An unknown error occured. Please try again.");
    }
}
public static int ReadNumber(int start, int end, int iteration)
{
    while (true)
    {
        Console.WriteLine("Input number {0}", iteration + 1);
        int n;
        if (!int.TryParse(Console.ReadLine(), out n))
            Console.WriteLine("The input isn't an integer number. Please try again.");
        else if (n < start || n > end)
            Console.WriteLine("The input number wasn't in the alowed range. Please try again.");
        else
            return n;
    }
}
for (int i = 0; i < 10; i++)
{
    int number = ReadNumber(start, end, i);
}

Context

StackExchange Code Review Q#62037, answer score: 3

Revisions (0)

No revisions yet.