×

C# Crash Course

Course Home C# Introduction and Setup C# Variables and Data Types C# Console Input and Output C# Operators and Expressions C# Conditional Statements - If and Else C# Switch Statements C# While and Do-While Loops C# For Loops C# Nested Loops C# Methods - Part 1 (Basics) C# Methods - Part 2 (ref, out, and Recursion) C# Arrays C# Number Systems (Binary and Hexadecimal) C# Exception Handling (Try-Catch) C# Random Numbers C# String Methods and Manipulation C# Course Summary and Best Practices


C# Exception Handling (Try-Catch)

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:

  1. Catch specific exceptions when possible
catch (FormatException)
{
    Console.WriteLine("Invalid format");
}
  1. Use TryParse for input validation
if (int.TryParse(input, out int result))
{
    // Valid input
}
  1. Provide meaningful error messages
catch (Exception ex)
{
    Console.WriteLine($"Error: {ex.Message}");
}

❌ DON'T:

  1. Don't catch exceptions you can't handle
catch
{
    // Do nothing - BAD!
}
  1. 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;
}
  1. 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