Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to treat and test flow control if not with exceptions with c#?

What's the right way to treat and test flow control on methods that are void if not with exceptions? I've seen that Microsoft do not recomend such practice so what's the right way?

This is how how I'm treating parameters that shouldn't be accepted in my method:

    public void RentOutCar(ReservationInfo reservationInfo) 
    {
        try
        {
            if (string.IsNullOrEmpty(reservationInfo.ReservationNumber) || string.IsNullOrWhiteSpace(reservationInfo.ReservationNumber))
            {
                throw new ArgumentException("Reservation Number is null or empty.");
            }
            if (reservationInfo == null)
            {
                throw new ArgumentNullException("Null Reservation info.");
            }
            if (reservationInfo.Car == null)
            {
                throw new ArgumentNullException("No car registered to rent.");
            }
            if (reservationInfo.RentalDatetime == DateTime.MinValue || reservationInfo.RentalDatetime == DateTime.MaxValue)
            {
                throw new ArgumentException("Rental Date has an unreal value.");
            }
            if (reservationInfo.Car.Mileage <0)
            {
                throw new ArgumentOutOfRangeException("Mileage can't be less than 0.");
            }

            reserverationsRegister.ReservationsDone.Add(reservationInfo);
        }
        catch (Exception) 
        {
            throw;
        }

    }
like image 497
Hejoi Avatar asked Feb 09 '23 22:02

Hejoi


1 Answers

This is not what Microsoft mean when they say you should not control flow with exceptions.

While the use of exception handlers to catch errors and other events that disrupt program execution is a good practice, the use of exception handler as part of the regular program execution logic can be expensive and should be avoided.

In other words, you should not throw (and subsequently catch) exceptions in situations where the code in the try block is likely to throw and represents legitimate program logic.

A contrived example of controlling flow with exceptions may look like:

int x = GetUserInput();
try
{
    MustAcceptPositiveInput(x);
}
catch (InputIsNonPositiveException)
{
    MustAcceptNonPositiveInput(x);
}

The equivalent 'correct' code may look like:

int x = GetUserInput();
if (x > 0)
{
    MustAcceptPositiveInput(x);
}
else
{
    MustAcceptNonPositiveInput(x);
}

Exceptions should be reserved for exceptional situations, those which are not part of expected program execution. It results in more readable, less surprising and more performant code.

What you are doing in your code is fine (except for the redundant try-catch and faulty order of tests as @Clay mentions), you are validating inputs for exceptional values, those which your code was not meant to handle.

like image 134
Rotem Avatar answered Feb 11 '23 12:02

Rotem