Codecademy Logo

C# Exceptions

Exception Definition

Exceptions are events that occur during the execution of a program, disrupting the normal flow of instructions.

int a = 1;
int b = 0;
int c = a/b; // This line produces a System.DivideByZeroException.
int d = c; // This line is never executed.

Custom Exceptions

In C#, system-defined exceptions are pre-defined by the .NET framework, while application-defined exceptions are custom exceptions created by developers.

// Here we define a custom exception
public class InvalidAgeException : Exception
{
public InvalidAgeException(string message) : base(message)
{
}
}

Try…Catch…Finally

In C#, try, catch, and finally blocks are used to test code for exceptions and handle them if necessary.

int numerator = 10;
int denominator = 0;
int result = numerator / denominator;
try // We catch any exception in this block.
{
int numerator = 10;
int denominator = 0;
int result = numerator / denominator;
}
catch (Exception ex) // This block runs if there is an exception.
{
Console.WriteLine("An exception occurred.");
}
finally // This block always runs after the prior two blocks.
{
Console.WriteLine("This message is always printed, even if an exception occurs.");
}

Common Exceptions

In C#, some common system-defined exceptions include NullReferenceException, IndexOutOfRangeException, InvalidOperationException, ArgumentException, IOException, and FormatException.

  • NullReferenceException: Occurs when trying to use a null object reference.
  • IndexOutOfRangeException: Occurs when accessing an array element with an invalid index.
  • InvalidOperationException: Occurs when a method call is invalid for the object’s current state.
  • ArgumentException: Occurs when a method is called with an invalid argument.
  • IOException: Occurs when there’s an error accessing a stream, file, or directory.
  • FormatException: Occurs when the format of an argument is invalid.

Exception Filters

In C#, exception filters, using the keyword when, allow handling exceptions based on specific conditions within catch blocks.

try
{
// Make an HTTP request for a url provided by the user
var response = await client.GetAsync(url);
}
// This catch block has a filter which must be true for the exception to be caught.
catch (HttpRequestException ex) when (ex.StatusCode == 404)
{
Console.WriteLine("The resource requested was not found, try a different URL.");
}
// If the exception is not caught with the filter, the next block will try to catch the error.
catch (HttpRequestException ex)
{
// This would handle any HTTP request exception that is not a 404
Console.WriteLine("An error occurred while making the request: " + ex.Message);
}

Exception Propagation

In C#, exception propagation refers to how exceptions move up the call stack, and rethrowing exceptions involves passing the caught exception up to a higher level.

class Product {
public string Name { get; set; }
public int Quantity {
get { return _quantity; }
set {
if (value < 0) {
// The setter throws the exception, but it is up to the caller to deal with not being able to set a quantity
// The error is propagated up to the caller
throw new ArgumentOutOfRangeException("Quantity cannot be negative.");
}
_quantity = value;
}
}
}
class Program
{
static void Main(string[] args)
{
Product product = new Product();
Console.WriteLine("Enter a product name: ");
string name = Console.ReadLine();
product.Name = name;
while (true)
{
Console.WriteLine("Enter a quantity: ");
int quantity = int.Parse(Console.ReadLine());
try
{
// The exception is thrown here when the entered quantity is negative
// The error happens in the Product class, but it is caught here
product.Quantity = quantity;
// The loop will only exit when the quantity is set successfully
break;
}
catch (ArgumentOutOfRangeException ex)
{
// We are providing a message to the user that the quantity cannot be negative
Console.WriteLine(ex.Message, "Please enter a non-negative quantity.");
}
}
}
}

Custom Exception Classes

In C#, custom exception classes are created and implemented to handle application-specific errors effectively.

// Create a custom exception class
public class InvalidAgeException : Exception
{
public InvalidAgeException(string message) : base(message)
{
}
}
public class Program
{
static void ValidateAge(int age)
{
if (age < 0 || age > 120)
{
// Throw the custom exception class
throw new InvalidAgeException("Age must be between 0 and 120.");
}
}
}

Exception Best Practice

Best practices for exception handling include knowing when to throw exceptions, when to catch them, and avoiding the overuse of exceptions.

  • Exceptions should be used to handle exceptional conditions, not for regular control flow.
  • Catch specific exceptions so you can handle different types of exceptions differently.
  • Clean up resources in a finally block.

Throwing Exceptions

In C#, the throw keyword allows developers to explicitly generate exceptions in their code, enabling them to signal specific error conditions and validate method arguments, thus contributing to more robust and maintainable applications.

if (age < 0)
{
throw new ArgumentException("Age cannot be negative.");
}

Learn more on Codecademy