Skip to main content
ANVISoftware Solutions
Lesson 12 of 15Beginner14 min

Errors and Exceptions

By the end of this lesson

Read an error message accurately, and handle failure deliberately instead of suppressing it.

Things go wrong. A file is missing, a network call times out, a user types "twelve" where a number was expected. When something goes wrong that the program cannot continue past, it throws an exception.

An exception is not a crash. It is a report. If nothing handles it, the program stops — but the report tells you what happened and where.

Reading the message

A typical exception
Text
Unhandled exception. System.FormatException: The input string 'twelve' was not in a correct format.
   at System.Number.ThrowOverflowOrFormatException(...)
   at System.Int32.Parse(String s)
   at Program.<Main>$(String[] args) in /app/Program.cs:line 7
  • FormatException is the kind of problem — the text was not a number.
  • The message states exactly which value caused it: 'twelve'.
  • The indented lines are the stack trace, reading from the deepest call upward. The last line is usually the most useful: your file, line 7.

Handling it

try / catch
C#
Console.Write("Enter your age: ");
string? input = Console.ReadLine();

try
{
    int age = int.Parse(input!);
    Console.WriteLine($"Next year you will be {age + 1}.");
}
catch (FormatException)
{
    Console.WriteLine("That was not a whole number. Please enter digits only.");
}
  • Code that might fail goes in the try block.
  • If a FormatException occurs, the catch block runs instead of the program stopping.
  • Catching the specific exception type matters — see the warning below.
Often better: check instead of catching
C#
Console.Write("Enter your age: ");
string? input = Console.ReadLine();

if (int.TryParse(input, out int age))
{
    Console.WriteLine($"Next year you will be {age + 1}.");
}
else
{
    Console.WriteLine("That was not a whole number. Please enter digits only.");
}
  • TryParse returns true or false rather than throwing. Invalid input is an expected outcome here, not an exceptional one.
  • out int age declares the variable and fills it in when parsing succeeds.
  • Use exceptions for the genuinely unexpected; use checks for things you know will happen regularly.

Exceptions you will meet early:

  • FormatException — text could not be converted to the requested type
  • NullReferenceException — you used something that had no value
  • IndexOutOfRangeException — you asked for a position that does not exist
  • DivideByZeroException — whole-number division by zero
  • FileNotFoundException — the file is not where you said it was

Summary

  • An exception is a report of a problem, not merely a crash — read it
  • In a stack trace, find the first line that refers to your own code
  • Use checks like TryParse for expected problems, exceptions for unexpected ones
  • Never swallow an exception silently; hidden failure costs more than visible failure

Practice

Attempt each one before opening the solution. Getting it wrong first is how the idea sticks.

Try it yourself

Try it yourself

Write a program that asks for two numbers and divides the first by the second. Handle both invalid input and division by zero, with a different message for each.

Show solution

Both problems are foreseeable, so both are checks rather than exception handling. That keeps the flow readable and the messages specific.

C#
Console.Write("First number:  ");
string? firstInput = Console.ReadLine();

Console.Write("Second number: ");
string? secondInput = Console.ReadLine();

if (!int.TryParse(firstInput, out int first) || !int.TryParse(secondInput, out int second))
{
    Console.WriteLine("Both values must be whole numbers.");
}
else if (second == 0)
{
    Console.WriteLine("Cannot divide by zero.");
}
else
{
    decimal result = (decimal)first / second;
    Console.WriteLine($"{first} / {second} = {result}");
}

Think about it

Think about it

Why is an empty catch block considered one of the worst things you can write, even though the program stops crashing?

Show solution

Because the program does not actually work — it only stops reporting that it does not work. Execution continues with data in an unknown state, so the real damage happens later and further away from the cause.

A crash is loud and traceable. Silent incorrect behaviour is neither, and it is far more expensive to diagnose.

Knowledge check

Nothing is recorded and there is no score. The explanation appears either way.

A user is likely to type text into a field that expects a number. What is the better approach?

Saved in this browser only.