Read the syntax
try contains an operation that may throw; a matching catch handles a particular exception. finally runs when control leaves the try/catch, including after an exception, except in process-ending situations.
Throw specific exceptions for genuine exceptional conditions, and use TryParse for ordinary invalid input. A using statement or declaration disposes supported resources when their scope ends.
Syntax
try {\n // risky code\n} catch (ExceptionType e) {\n // handle it\n} finally {\n // always runs\n}Examples
Basic try / catch
Catching an exception instead of letting the program crash.
try
{
int result = 10 / int.Parse("0");
}
catch (DivideByZeroException e)
{
Console.WriteLine($"Error: {e.Message}");
}
Console.WriteLine("Program continues running");- Catching an exception instead of letting the program crash.
- try contains an operation that may throw; a matching catch handles a particular exception. finally runs when control leaves the try/catch, including after an exception, except in process-ending situations.
- Parsing 0 succeeds, but dividing 10 by that zero throws DivideByZeroException. The catch prints the error, then execution continues to the final line.
Catching Multiple Exception Types
Handling different exceptions differently with multiple catch blocks.
void Process(string input)
{
try
{
int number = int.Parse(input);
int result = 100 / number;
Console.WriteLine(result);
}
catch (FormatException)
{
Console.WriteLine($"Not a valid number: {input}");
}
catch (DivideByZeroException)
{
Console.WriteLine("Cannot divide by zero");
}
}
Process("abc"); // Not a valid number: abc
Process("0"); // Cannot divide by zero
Process("5"); // 20- Handling different exceptions differently with multiple catch blocks.
- try contains an operation that may throw; a matching catch handles a particular exception. finally runs when control leaves the try/catch, including after an exception, except in process-ending situations.
- abc causes FormatException, 0 causes DivideByZeroException, and 5 produces 20. Different catch blocks communicate each failure separately.
finally and using
Code in finally always executes; the using statement automatically disposes resources, even on exception.
void ReadFile()
{
Console.WriteLine("Opening file...");
try
{
throw new InvalidOperationException("File not found");
}
catch (InvalidOperationException e)
{
Console.WriteLine($"Error: {e.Message}");
}
finally
{
Console.WriteLine("Closing file..."); // always runs
}
}
ReadFile();- Code in finally always executes; the using statement automatically disposes resources, even on exception.
- try contains an operation that may throw; a matching catch handles a particular exception. finally runs when control leaves the try/catch, including after an exception, except in process-ending situations.
- ReadFile throws deliberately, catch prints its message, and finally prints Closing file.... No file is actually opened in this example despite its method name.
Custom Exceptions
Defining and throwing your own exception type for domain-specific error handling.
BankAccount account = new BankAccount(100);
try
{
account.Withdraw(200);
}
catch (InsufficientFundsException e)
{
Console.WriteLine($"Transaction failed: {e.Message}");
}
public class InsufficientFundsException : Exception
{
public InsufficientFundsException(string message) : base(message) { }
}
public class BankAccount
{
private double _balance;
public BankAccount(double balance) => _balance = balance;
public void Withdraw(double amount)
{
if (amount > _balance)
throw new InsufficientFundsException("Not enough funds for this withdrawal");
_balance -= amount;
}
}- Defining and throwing your own exception type for domain-specific error handling.
- try contains an operation that may throw; a matching catch handles a particular exception. finally runs when control leaves the try/catch, including after an exception, except in process-ending situations.
- Withdrawing 200 from a balance of 100 throws the custom exception. The matching catch prints its message and prevents the example from terminating unhandled.
Best practices
- Catch specific exception types rather than a broad catch (Exception e), so unrelated bugs are not accidentally silenced
- Use finally (or better, a using statement/declaration) for cleanup code that absolutely must run, like closing files or database connections
- Create custom exception classes, deriving from Exception, for domain-specific errors that callers should be able to catch distinctly
- Don't use exceptions for routine control flow when a simple if check (or TryParse-style pattern) would do - they carry real performance overhead
Runtime & versions
.NET runtime. Feature availability depends on the language and runtime version used by your project; consult the official reference below.
C# language reference