Keep your program from crashing when something goes wrong: the exception concept, try/catch/finally, throw, your own exception class and cleanup with using.
What is an exception?
While a program runs, an unexpected situation occurs: dividing by zero, opening a file that doesn't exist, accessing an index that is not in the list... In these cases .NET throws an exception object. If it is not caught, the program prints a message and closes. Our goal is to be prepared for these situations and to respond to the user properly.
try - catch
try
{
Console.Write("Enter a number: ");
int number = int.Parse(Console.ReadLine()!);
Console.WriteLine($"100 / {number} = {100 / number}");
}
catch (FormatException)
{
Console.WriteLine("That is not a number.");
}
catch (DivideByZeroException)
{
Console.WriteLine("You cannot divide by zero.");
}
You put the risky code in the try block. If an exception occurs inside it, the flow jumps immediately to the matching catch block. By writing several catch blocks you can handle different errors separately; order them from specific to general.
Enter a number: abc
That is not a number.
Accessing the exception object
try
{
int[] array = { 1, 2, 3 };
Console.WriteLine(array[5]);
}
catch (Exception ex)
{
Console.WriteLine($"Error type: {ex.GetType().Name}");
Console.WriteLine($"Message: {ex.Message}");
}
Error type: IndexOutOfRangeException
Message: Index was outside the bounds of the array.
Error messages can come in English or in another language depending on .NET's language setting. Exception is the ancestor of all errors; a general catch placed at the very end works as a catch-all.
finally: the block that runs in every case
Cleanup jobs such as closing a file or releasing a connection must be done whether there was an error or not. The finally block is for this:
StreamReader? reader = null;
try
{
reader = new StreamReader("measurements.txt");
Console.WriteLine(reader.ReadLine());
}
catch (FileNotFoundException)
{
Console.WriteLine("measurements.txt was not found.");
}
finally
{
reader?.Dispose(); // close it if it is open
Console.WriteLine("Cleanup done.");
}
The ?. operator means "call it if the object is not null".
using: a shortcut for cleanup
For objects that must be closed, such as files, the using declaration closes the object automatically when the block ends; it saves you from writing finally:
try
{
using var reader = new StreamReader("measurements.txt");
string? line;
while ((line = reader.ReadLine()) != null)
{
Console.WriteLine(line);
}
}
catch (FileNotFoundException)
{
Console.WriteLine("No such file.");
}
throw: raise the error yourself
If a method receives invalid input, instead of quietly returning a wrong result it should throw an error:
static double Current(double voltage, double resistance)
{
if (resistance <= 0)
throw new ArgumentOutOfRangeException(nameof(resistance), "Resistance must be greater than zero.");
return voltage / resistance;
}
try
{
Console.WriteLine(Current(5, 0));
}
catch (ArgumentOutOfRangeException ex)
{
Console.WriteLine("Invalid: " + ex.ParamName);
}
Invalid: resistance
Writing your own exception class
For an error specific to your field, you can derive from Exception:
try
{
double current = 12.5;
if (current > 10) throw new OvercurrentException(current);
}
catch (OvercurrentException ex)
{
Console.WriteLine(ex.Message);
}
class OvercurrentException : Exception
{
public double Current { get; }
public OvercurrentException(double current)
: base($"Current limit exceeded: {current} A")
{
Current = current;
}
}
Current limit exceeded: 12.5 A
Anti-pattern: Don't write catch (Exception) { } and swallow the error. The problem gets hidden and becomes very hard to find later. If you catch it, either fix it, log it, or rethrow it (throw;).
Tip: For expected situations (the user typed an invalid number), prefer controlled methods such as TryParse instead of an exception. Exceptions are for things that "should not happen"; they are also relatively slow.
Try it yourself
Write a program that asks the user for a file name and prints the number of lines in the file. Give three separate messages: if the file doesn't exist, if there is no permission to read it (UnauthorizedAccessException), and if any other error occurs. Open the file with using.
// Mini quiz
Click an option; you will see right away, with the reason, whether it is correct or not.
Mark it when you finish: your progress is saved and you earn +20 XP.
Tip: ← → keys let you move between lessons.