What is an Exception?
An exception is an error that occurs during program execution. If not handled, it crashes your program.
Common Exceptions
// FormatException - Invalid input format
int iAge = int.Parse("abc"); // CRASH! Can't convert "abc" to int
// DivideByZeroException - Division by zero
int iResult = 10 / 0; // CRASH!
// IndexOutOfRangeException - Invalid array index
int[] iNumbers = { 1, 2, 3 };
int iValue = iNumbers[5]; // CRASH! Index 5 doesn't exist
// NullReferenceException - Using null object
string sName = null;
int iLength = sName.Length; // CRASH! sName is null
The try-catch Block
Use try-catch to handle exceptions gracefully without crashing.
Basic Syntax
try
{
// Code that might cause an exception
}
catch
{
// Code to handle the exception
}
Example 1: Basic Exception Handling
using System;
namespace ExceptionHandling
{
class Program
{
static void Main(string[] args)
{
try
{
Console.Write("Enter a number: ");
int iNumber = int.Parse(Console.ReadLine());
Console.WriteLine($"You entered: {iNumber}");
}
catch
{
Console.WriteLine("Invalid input! Please enter a valid number.");
}
Console.WriteLine("\nPress any key to exit...");
Console.ReadKey();
}
}
}
// If user enters "abc": Shows error message, program continues
// If user enters "25": Shows "You entered: 25"
Example 2: Division by Zero
try
{
Console.Write("Enter first number: ");
int iNum1 = int.Parse(Console.ReadLine());
Console.Write("Enter second number: ");
int iNum2 = int.Parse(Console.ReadLine());
int iResult = iNum1 / iNum2;
Console.WriteLine($"Result: {iResult}");
}
catch
{
Console.WriteLine("Error occurred!");
}
Specific Exception Types
You can catch specific exception types to handle them differently.
Syntax
try
{
// Code
}
catch (ExceptionType ex)
{
// Handle specific exception
}
Example: Multiple Catch Blocks
try
{
Console.Write("Enter a number: ");
int iNumber = int.Parse(Console.ReadLine());
int[] iNumbers = { 10, 20, 30 };
Console.WriteLine(iNumbers[iNumber]);
}
catch (FormatException)
{
Console.WriteLine("Invalid format! Please enter a number.");
}
catch (IndexOutOfRangeException)
{
Console.WriteLine("Index out of range!");
}
catch (Exception ex)
{
Console.WriteLine($"An error occurred: {ex.Message}");
}
Using Exception Object
The exception object contains information about the error.
try
{
int iNumber = int.Parse("abc");
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
// Output: Error: Input string was not in a correct format.
}
Practical Examples from Course
Example 1: Loan Eligibility with Try-Catch (Worksheet 5)
using System;
namespace LoanEligibility
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Welcome to the Loan Eligibility Checker!");
try
{
Console.Write("Enter your monthly income (R): ");
decimal mMonthlyIncome = decimal.Parse(Console.ReadLine());
Console.Write("Enter your credit score (300-850): ");
int iCreditScore = int.Parse(Console.ReadLine());
Console.Write("Are you employed? (Y/N): ");
char cEmployed = char.Parse(Console.ReadLine().ToUpper());
bool isEmployed = (cEmployed == 'Y');
// Check eligibility
bool isEligible = CheckLoanEligibility(mMonthlyIncome, iCreditScore, isEmployed);
DisplayEligibilityResult(isEligible, mMonthlyIncome, iCreditScore, isEmployed);
}
catch
{
Console.WriteLine("\nError: Please enter valid numbers for income and credit score.");
}
Console.WriteLine("\nPress any key to exit...");
Console.ReadKey();
}
static bool CheckLoanEligibility(decimal mIncome, int iCreditScore, bool isEmployed)
{
if (isEmployed && mIncome >= 2000 && iCreditScore >= 600)
{
return true;
}
return false;
}
static void DisplayEligibilityResult(bool isEligible, decimal mIncome, int iCreditScore, bool isEmployed)
{
Console.WriteLine("\n--- Eligibility Result ---");
Console.WriteLine($"Monthly Income: R{mIncome:0.00}");
Console.WriteLine($"Credit Score: {iCreditScore}");
Console.WriteLine($"Employment Status: {(isEmployed ? "Employed" : "Not Employed")}");
if (isEligible)
{
Console.WriteLine("Result: Congratulations! You are eligible for a loan.");
}
else
{
Console.WriteLine("Result: Sorry, you are not eligible for a loan.");
ProvideFeedback(mIncome, iCreditScore, isEmployed);
}
}
static void ProvideFeedback(decimal mIncome, int iCreditScore, bool isEmployed)
{
Console.WriteLine("Reasons for ineligibility:");
if (!isEmployed)
{
Console.WriteLine("- You must be employed to qualify.");
}
if (mIncome < 2000)
{
Console.WriteLine("- Monthly income must be at least R2000.");
}
if (iCreditScore < 600)
{
Console.WriteLine("- Credit score must be at least 600.");
}
}
}
}
Example 2: Recursive Sum with Try-Catch (Practical Test 5)
using System;
namespace RecursiveSum
{
class Program
{
static void Main(string[] args)
{
try
{
Console.Write("Enter a: ");
int iA = int.Parse(Console.ReadLine());
Console.Write("Enter b: ");
int iB = int.Parse(Console.ReadLine());
int iSum = Sum(iA, iB);
string sOutput = String.Format("\nThe sum of {0} and {1} is {2}", iA, iB, iSum);
Console.WriteLine(sOutput);
}
catch
{
Console.WriteLine("\nInvalid input.");
}
Console.WriteLine("\nPress any key to exit...");
Console.ReadKey();
}
static int Sum(int iA, int iB)
{
if (iA == 0)
{
return iB;
}
else if (iB == 0)
{
return iA;
}
else
{
return Sum(iA - 1, iB) + 1;
}
}
}
}
Example 3: Division with Try-Catch (Worksheet 5)
using System;
namespace RecursiveDivision
{
class Program
{
static void Main(string[] args)
{
try
{
Console.Write("First number: ");
int iA = int.Parse(Console.ReadLine());
Console.Write("Second number: ");
int iB = int.Parse(Console.ReadLine());
int iQuotient = Quotient(iA, iB);
Console.WriteLine($"\nThe quotient of {iA} / {iB} is {iQuotient}");
}
catch (Exception ex)
{
Console.WriteLine("\nInvalid input");
}
Console.WriteLine("\nPress any key to exit...");
Console.ReadKey();
}
static int Quotient(int iA, int iB)
{
if (iA < iB)
{
return 0;
}
else
{
return 1 + Quotient(iA - iB, iB);
}
}
}
}
TryParse vs Try-Catch
Using Try-Catch (Less Preferred)
try
{
Console.Write("Enter age: ");
int iAge = int.Parse(Console.ReadLine());
Console.WriteLine($"Age: {iAge}");
}
catch
{
Console.WriteLine("Invalid input");
}
Using TryParse (Preferred for Input Validation)
Console.Write("Enter age: ");
bool isValid = int.TryParse(Console.ReadLine(), out int iAge);
if (isValid)
{
Console.WriteLine($"Age: {iAge}");
}
else
{
Console.WriteLine("Invalid input");
}
When to Use Which?
Use TryParse When: ✅ Validating user input ✅ You expect invalid input ✅ Better performance
Use Try-Catch When: ✅ Unexpected errors might occur ✅ Working with file operations ✅ Database operations ✅ Complex operations that might fail
The finally Block
The finally
block always executes, whether an exception occurred or not.
Syntax
try
{
// Code that might throw exception
}
catch
{
// Handle exception
}
finally
{
// Always executes
}
Example
try
{
Console.Write("Enter a number: ");
int iNumber = int.Parse(Console.ReadLine());
Console.WriteLine($"Number: {iNumber}");
}
catch
{
Console.WriteLine("Invalid input");
}
finally
{
Console.WriteLine("This always runs!");
}
// If valid input: Shows number, then "This always runs!"
// If invalid input: Shows "Invalid input", then "This always runs!"
Throwing Exceptions
You can throw your own exceptions.
static void CheckAge(int iAge)
{
if (iAge < 0)
{
throw new Exception("Age cannot be negative!");
}
if (iAge > 150)
{
throw new Exception("Age is too high!");
}
Console.WriteLine($"Valid age: {iAge}");
}
// Usage
try
{
CheckAge(-5);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message); // "Age cannot be negative!"
}
Common Exception Types
Exception | Cause |
---|---|
FormatException |
Invalid format for conversion |
DivideByZeroException |
Division by zero |
IndexOutOfRangeException |
Invalid array/string index |
NullReferenceException |
Accessing null object |
OverflowException |
Number too large/small |
ArgumentException |
Invalid argument to method |
InvalidOperationException |
Invalid operation |
Practice Exercises
Exercise 1: Safe Calculator
Create a calculator that handles all possible errors: - Invalid input - Division by zero - Invalid operator
Exercise 2: Array Element Access
Create a program that safely accesses array elements with error handling.
Exercise 3: File Age Validator
Create a program that validates age input: - Must be a number - Must be between 0 and 120 - Use both try-catch and validation
Complete Example: Robust Input Handler
using System;
namespace RobustInput
{
class Program
{
static void Main(string[] args)
{
try
{
int iAge = GetValidAge();
double dHeight = GetValidHeight();
string sName = GetValidName();
Console.WriteLine("\n--- Your Information ---");
Console.WriteLine($"Name: {sName}");
Console.WriteLine($"Age: {iAge}");
Console.WriteLine($"Height: {dHeight:0.00}m");
}
catch (Exception ex)
{
Console.WriteLine($"\nAn error occurred: {ex.Message}");
}
Console.WriteLine("\nPress any key to exit...");
Console.ReadKey();
}
static int GetValidAge()
{
while (true)
{
try
{
Console.Write("Enter your age (0-120): ");
int iAge = int.Parse(Console.ReadLine());
if (iAge < 0 || iAge > 120)
{
throw new Exception("Age must be between 0 and 120");
}
return iAge;
}
catch (FormatException)
{
Console.WriteLine("Error: Please enter a valid number\n");
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}\n");
}
}
}
static double GetValidHeight()
{
while (true)
{
try
{
Console.Write("Enter your height in meters (0.5-2.5): ");
double dHeight = double.Parse(Console.ReadLine());
if (dHeight < 0.5 || dHeight > 2.5)
{
throw new Exception("Height must be between 0.5 and 2.5 meters");
}
return dHeight;
}
catch (FormatException)
{
Console.WriteLine("Error: Please enter a valid number\n");
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}\n");
}
}
}
static string GetValidName()
{
while (true)
{
Console.Write("Enter your name: ");
string sName = Console.ReadLine();
if (string.IsNullOrWhiteSpace(sName))
{
Console.WriteLine("Error: Name cannot be empty\n");
continue;
}
return sName;
}
}
}
}
Best Practices
✅ DO:
- Catch specific exceptions when possible
catch (FormatException)
{
Console.WriteLine("Invalid format");
}
- Use TryParse for input validation
if (int.TryParse(input, out int result))
{
// Valid input
}
- Provide meaningful error messages
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
❌ DON'T:
- Don't catch exceptions you can't handle
catch
{
// Do nothing - BAD!
}
- Don't use exceptions for flow control
// BAD - Use if statement instead
try
{
int result = 10 / iNumber;
}
catch
{
// Handle division by zero
}
// GOOD
if (iNumber != 0)
{
int result = 10 / iNumber;
}
- Don't hide errors without logging
catch
{
// Error hidden! BAD!
}
Common Mistakes to Avoid
❌ Empty catch block:
try
{
int iNumber = int.Parse(Console.ReadLine());
}
catch
{
// Nothing here - error is hidden!
}
✅ Correct:
try
{
int iNumber = int.Parse(Console.ReadLine());
}
catch
{
Console.WriteLine("Invalid input!");
}
❌ Catching too broadly:
try
{
// Lots of code
}
catch (Exception ex)
{
Console.WriteLine("Error"); // Which error? Where?
}
✅ Better:
try
{
// Specific operation
}
catch (FormatException)
{
Console.WriteLine("Invalid format");
}
catch (DivideByZeroException)
{
Console.WriteLine("Cannot divide by zero");
}
Key Takeaways
✅ Try-catch prevents program crashes ✅ Use try-catch for unexpected errors ✅ Use TryParse for input validation ✅ Catch specific exceptions when possible ✅ Always provide user-friendly error messages ✅ The finally block always executes ✅ Don't hide exceptions - handle them properly ✅ Use exceptions for exceptional situations, not normal flow
Next Topic: C# Random Numbers