C# Exception Handling


예외 처리 소개 (Introduction to Exception Handling)

예외 처리란 프로그램 실행 중 발생할 수 있는 오류를 처리하는 메커니즘입니다. 예외는 예기치 않은 상황을 나타내며, 이러한 상황을 적절하게 처리하지 않으면 프로그램이 중단될 수 있습니다. C#에서는 try, catch, finally 블록을 사용하여 예외를 처리합니다.

예외 처리 기본 구조 (Basic Structure of Exception Handling)

예외 처리는 try 블록 내에서 예외가 발생할 가능성이 있는 코드를 실행하고, catch 블록에서 예외를 처리하며, finally 블록에서 예외 발생 여부와 상관없이 실행할 코드를 작성합니다.

try
{
    // 예외가 발생할 수 있는 코드 (Code that may throw an exception)
}
catch (Exception ex)
{
    // 예외 처리 코드 (Code to handle the exception)
}
finally
{
    // 항상 실행되는 코드 (Code that always runs)
}

예외 처리 예제 (Exception Handling Example)

using System;

namespace ExceptionHandlingExample
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                int divisor = 0;
                int result = 10 / divisor;
            }
            catch (DivideByZeroException ex)
            {
                Console.WriteLine("Cannot divide by zero.");
                Console.WriteLine($"Exception Message: {ex.Message}");
            }
            finally
            {
                Console.WriteLine("This block is always executed.");
            }
        }
    }
}

이 예제에서 10 / divisor에서 DivideByZeroException이 발생합니다. catch 블록에서 예외를 처리하고, finally 블록은 항상 실행됩니다.

다양한 예외 처리 (Handling Different Types of Exceptions)

여러 종류의 예외를 처리할 때는 각 예외 타입에 대한 catch 블록을 사용할 수 있습니다. 보다 구체적인 예외부터 처리하고, 마지막에 일반적인 Exception 타입을 처리합니다.

using System;

namespace ExceptionHandlingExample
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                int[] numbers = { 1, 2, 3 };
                int invalidIndexValue = numbers[5];
            }
            catch (IndexOutOfRangeException ex)
            {
                Console.WriteLine("Index out of range.");
                Console.WriteLine($"Exception Message: {ex.Message}");
            }
            catch (Exception ex)
            {
                Console.WriteLine("An unexpected error occurred.");
                Console.WriteLine($"Exception Message: {ex.Message}");
            }
            finally
            {
                Console.WriteLine("This block is always executed.");
            }
        }
    }
}

이 예제에서 numbers[5]에서 IndexOutOfRangeException이 발생합니다. 첫 번째 catch 블록이 이 예외를 처리하고, 다른 예외는 두 번째 catch 블록에서 처리합니다.

사용자 정의 예외 (Custom Exceptions)

사용자 정의 예외를 만들어 특정 상황을 처리할 수 있습니다. 사용자 정의 예외는 Exception 클래스를 상속하여 구현합니다.

using System;

namespace ExceptionHandlingExample
{
    // 사용자 정의 예외 클래스 (Custom Exception Class)
    public class NegativeNumberException : Exception
    {
        public NegativeNumberException(string message) : base(message) { }
    }

    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                int number = -5;
                if (number < 0)
                {
                    throw new NegativeNumberException("Negative numbers are not allowed.");
                }
            }
            catch (NegativeNumberException ex)
            {
                Console.WriteLine($"Custom Exception: {ex.Message}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"General Exception: {ex.Message}");
            }
            finally
            {
                Console.WriteLine("This block is always executed.");
            }
        }
    }
}

이 예제에서는 음수가 입력되면 NegativeNumberException을 발생시키고, 이를 catch 블록에서 처리합니다.

예외 재발생 (Re-throwing Exceptions)

예외를 처리한 후에 예외를 다시 발생시킬 수 있습니다. 이는 상위 호출 스택에서 예외를 다시 처리하도록 할 때 유용합니다.

using System;

namespace ExceptionHandlingExample
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                MethodA();
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Exception caught in Main: {ex.Message}");
            }
        }

        static void MethodA()
        {
            try
            {
                MethodB();
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Exception caught in MethodA: {ex.Message}");
                throw; // 예외 재발생 (Re-throwing the exception)
            }
        }

        static void MethodB()
        {
            throw new InvalidOperationException("An error occurred in MethodB.");
        }
    }
}

이 예제에서는 MethodB에서 발생한 예외를 MethodA에서 처리한 후, 예외를 다시 발생시켜 Main 메서드에서 최종적으로 처리합니다.

예외 필터 (Exception Filters)

C# 6부터는 예외 필터를 사용할 수 있습니다. 예외 필터는 catch 블록이 특정 조건을 만족하는 경우에만 실행되도록 합니다.

using System;

namespace ExceptionHandlingExample
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                int divisor = 0;
                int result = 10 / divisor;
            }
            catch (DivideByZeroException ex) when (ex.Message.Contains("zero"))
            {
                Console.WriteLine("Filtered exception: Cannot divide by zero.");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"General Exception: {ex.Message}");
            }
            finally
            {
                Console.WriteLine("This block is always executed.");
            }
        }
    }
}

이 예제에서는 DivideByZeroException 예외 메시지가 “zero”를 포함하는 경우에만 catch 블록이 실행됩니다.

예외 처리 종합 예제 (Comprehensive Example of Exception Handling)

using System;

namespace ExceptionHandlingExample
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Console.WriteLine("Enter a number:");
                int number = int.Parse(Console.ReadLine());

                if (number < 0)
                {
                    throw new ArgumentOutOfRangeException("number", "The number cannot be negative.");
                }

                int result = 10 / number;
                Console.WriteLine($"Result: {result}");
            }
            catch (FormatException ex)
            {
                Console.WriteLine("Input is not a valid number.");
                Console.WriteLine($"Exception Message: {ex.Message}");
            }
            catch (DivideByZeroException ex)
            {
                Console.WriteLine("Cannot divide by zero.");
                Console.WriteLine($"Exception Message: {ex.Message}");
            }
            catch (ArgumentOutOfRangeException ex)
            {
                Console.WriteLine($"Argument out of range: {ex.ParamName}");
                Console.WriteLine($"Exception Message: {ex.Message}");
            }
            catch (Exception ex)
            {
                Console.WriteLine("An unexpected error occurred.");
                Console.WriteLine($"Exception Message: {ex.Message}");
            }
            finally
            {
                Console.WriteLine("This block is always executed.");
            }
        }
    }
}

이 종합 예제에서는 다양한 예외 상황을 처리합니다. 입력 값이 숫자가 아닌 경우, 0으로 나누는 경우, 음수가 입력된 경우 등 여러 예외를 각각의 catch 블록에서 처리하고, 항상 실행되는 finally 블록을 포함합니다.


Posted in C#

Leave a Reply

Your email address will not be published. Required fields are marked *