Exceptions
Exceptions are unexpected conditions or errors in our program (e.g. data is not valid, arithmetic error, parsing error, etc.)
For example:
int i = 5;
int j = 0;
Console.WriteLine(i / j);
results in:
Unhandled Exception: System.DivideByZeroException: Attempted to divide by zero.
👎 It also contains awful variable names, but let’s fix one problem at a time.
We can avoid this error with logic:
int i = 5;
int j = 0;
if (j != 0) {
Console.WriteLine(i / j);
} // end if
else {
Console.WriteLine("Cannot divide by zero.");
} // end else
Or, we can catch the exception!
int i = 5;
int j = 0;
try { // we'll try to run the code in this block.
// if any of it fails, we jump to the catch block.
Console.WriteLine(i / j);
} // end try
catch { // this code will only run if there was an exception in the try block.
Console.WriteLine("Cannot divide by zero.");
} // end catch
Accessing Exception data
We can also view the specific exception message:
int i = 5;
int j = 0;
try {
Console.WriteLine(i / j);
} // end try
catch (Exception ex) {
Console.WriteLine("Cannot divide by zero.");
Console.WriteLine(ex.Message);
} // end catch
Which returns:
Cannot divide by zero. // our message
Attempted to divide by zero. // the Message in the Exception object
Common Use Cases
We can catch exceptions of many kinds. A common exception is when we parse our user’s input.
For example:
int userAge;
Console.WriteLine("How old are you?");
userAge = int.Parse(Console.ReadLine());
This works perfectly if the user enters a number. But what if the user enters something else, like the word “eight”?
🚨 An exception!
We can move this into a try
/catch
block:
int userAge;
Console.WriteLine("How old are you?");
try
{
userAge = int.Parse(Console.ReadLine());
} // end try
catch (Exception)
{
Console.WriteLine("Invalid input!");
} // end catch
Now, the program doesn’t crash, but instead returns a nice message back to the Console.
We can continue to build on this example by moving the code inside of a loop, which we remain in until the user enters a valid number:
int userAge;
bool validInput = false; // default value, will be set to true if parsing is successful
Console.WriteLine("How old are you?");
while (!validInput)
{
try
{
userAge = int.Parse(Console.ReadLine());
validInput = true;
} // end try
catch (Exception)
{
Console.WriteLine("Invalid input! Please re-enter.");
} // end catch
} // end while
Console.WriteLine("We got to the end!");
An alternative way to deal with parsing exceptions would be to use the .TryParse()
method. This returns a bool
that is true
if the parsing was successful, and false
otherwise, and when we call this method, we pass in a string
that we want to parse, and an out
reference of the variable where the parsed data should be stored.
For example:
string rawInputString = Console.ReadLine();
int userInt;
bool parsingSuccessful = int.TryParse(rawInputString, out userInt);
Throwing our own exceptions
We may also write methods which throw
exceptions in certain conditions.
We could have a method containing a segment of code that looks something like:
bool isValid;
// some code executes that sets isValid to true or false
if (isValid) {
Console.WriteLine("Input was valid.");
} // end if
else {
throw new Exception("Input is invalid.");
} // end else
The code calling this method would then need to handle the exception this method has thrown.
⚾ Everything that is thrown must be caught!