연습 - 예외 생성 및 던지기

완료됨

개발자는 종종 메서드 내에서 예외를 생성하고 던진 다음, 이 호출 스택 하단에서 이러한 예외를 처리할 수 있도록 잡아야 합니다. 예외 처리는 애플리케이션의 안정성을 보장하는 데 도움이 됩니다.

이 연습에서는 호출된 메서드 내에서 잠재적인 오류 조건을 포함하는 샘플 애플리케이션으로 시작합니다. 업데이트된 메서드는 throw 문제를 감지하면 예외가 발생합니다. 예외는 메서드를 호출하는 catch 코드 블록에서 처리됩니다. 그 결과 더 나은 사용자 환경을 제공하는 애플리케이션이 생성됩니다.

새 코드 프로젝트 만들기

첫 번째 단계는 이 모듈 중에 사용할 수 있는 코드 프로젝트를 만드는 것입니다.

  1. Visual Studio Code의 새 인스턴스를 엽니다.

  2. 파일 메뉴에서 폴더 열기를 선택합니다.

  3. 폴더 열기 대화 상자에서 Windows 데스크톱 폴더로 이동합니다.

  4. 폴더 열기 대화 상자에서 새 폴더를 선택합니다.

  5. 새 폴더의 이름을 ThrowExceptions101로 지정하고 폴더 선택을 선택합니다.

  6. 터미널 메뉴에서 새 터미널을 선택합니다.

    .NET CLI 명령을 사용하여 새 콘솔 앱을 만듭니다.

  7. 터미널 패널 명령 프롬프트에서 다음 명령을 입력합니다.

    dotnet new console
    
  8. 터미널 패널을 닫습니다.

샘플 애플리케이션 검토

다음 단계를 사용하여 샘플 애플리케이션을 로드하고 검토합니다.

  1. Program.cs 파일을 엽니다.

  2. 보기 메뉴에서 명령 팔레트를 선택합니다.

  3. 명령 프롬프트에 .net: g를 입력한 다음 .NET:을 선택합니다. 빌드 및 디버그를 위한 자산을 생성합니다.

  4. Program.cs 파일의 내용을 다음 코드로 바꿉니다.

    // Prompt the user for the lower and upper bounds
    Console.Write("Enter the lower bound: ");
    int lowerBound = int.Parse(Console.ReadLine());
    
    Console.Write("Enter the upper bound: ");
    int upperBound = int.Parse(Console.ReadLine());
    
    decimal averageValue = 0;
    
    // Calculate the sum of the even numbers between the bounds
    averageValue = AverageOfEvenNumbers(lowerBound, upperBound);
    
    // Display the value returned by AverageOfEvenNumbers in the console
    Console.WriteLine($"The average of even numbers between {lowerBound} and {upperBound} is {averageValue}.");
    
    // Wait for user input
    Console.ReadLine();
    
    static decimal AverageOfEvenNumbers(int lowerBound, int upperBound)
    {
        int sum = 0;
        int count = 0;
        decimal average = 0;
    
        for (int i = lowerBound; i <= upperBound; i++)
        {
            if (i % 2 == 0)
            {
                sum += i;
                count++;
            }
        }
    
        average = (decimal)sum / count;
    
        return average;
    }
    
  5. 코드를 검토하는 데 1분 정도 걸릴 수 있습니다.

    애플리케이션은 다음 작업을 수행합니다.

    1. 최상위 문은 Console.ReadLine() 문을 사용하여 lowerBoundupperBound의 값을 구합니다.

    2. 최상위 문은 lowerBoundupperBound을 인수로 하여 AverageOfEvenNumbers 메서드를 호출할 때 전달합니다.

    3. AverageOfEvenNumbers 메서드는 다음 작업을 수행합니다:

      1. 계산에 사용되는 지역 변수를 선언합니다.
      2. 루프 for를 사용하여 lowerBoundupperBound 사이의 짝수 합계를 계산합니다. 합계는 에 sum저장됩니다.
      3. 합계에 포함된 숫자 수를 계산합니다. 개수는 에 count저장됩니다.
      4. 합계 숫자의 평균을 변수에 저장 average합니다. 값 average 이 반환됩니다.
    4. 최상위 명령문은 콘솔에 반환된 AverageOfEvenNumbers 값을 출력한 후 실행이 중지됩니다.

디버그 환경 구성

샘플 애플리케이션은 콘솔에서 사용자 입력을 읽습니다. 디버그 콘솔 패널은 콘솔에서 입력을 읽는 것을 지원하지 않습니다. 디버거에서 이 애플리케이션을 실행하려면 launch.json 파일을 업데이트해야 합니다.

  1. 탐색기 보기를 사용하여 launch.json 파일을 엽니다.

  2. launch.json 파일에서 다음과 같이 console 특성을 업데이트합니다.

    // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
    "console":"integratedTerminal",
    

    console 특성의 기본값은 internalConsole이며 디버그 콘솔 패널에 맞춰집니다. 아쉽게도 디버그 콘솔 패널은 콘솔 입력을 지원하지 않습니다. integratedTerminal 설정은 콘솔 입력 및 출력을 지원하는 터미널 패널에 맞춰집니다.

  3. 변경 내용을 launch.json 파일에 저장한 다음 파일을 닫습니다.

  4. Visual Studio Code 실행 메뉴에서 디버깅 시작을 선택합니다.

  5. 터미널 패널로 전환합니다.

  6. “하한” 프롬프트에서 3을 입력합니다.

  7. “상한” 프롬프트에서 11을 입력합니다.

  8. 애플리케이션은 다음 메시지를 표시한 다음 일시 중지합니다.

    The average of even numbers between 3 and 11 is 7.
    
  9. 애플리케이션을 종료하려면 Enter 키를 누릅니다.

AverageOfEvenNumbers 메서드에서 예외를 던지세요.

메서드는 AverageOfEvenNumbers 하한보다 큰 상한을 예상합니다. DivideByZero 하한이 상한보다 크거나 같으면 오류가 발생합니다.

하한이 상한보다 크거나 같을 때 예외를 throw하도록 AverageOfEvenNumbers 메서드를 업데이트해야 합니다.

  1. 잠시 시간을 내어 문제를 해결하는 방법을 고려하세요.

    한 가지 옵션은 average 코드 블록 내에서 try의 계산을 래핑하고, catch 예외가 발생할 때 그 예외를 DivideByZero하는 것입니다. 예외를 다시 throw한 다음 호출 코드에서 처리할 수 있습니다.

    또 다른 옵션은 계산을 시작하기 전에 입력 매개 변수를 평가하는 것입니다. lowerBoundupperBound보다 크거나 같으면 예외를 발생시킬 수 있습니다.

    계산을 시작하기 전에 매개 변수를 평가하고 예외를 throw하는 것이 좋습니다.

  2. 어떤 예외 유형을 던질지 고려하세요.

    문제와 일치하는 두 가지 예외 유형이 있습니다.

    • ArgumentOutOfRangeExceptionArgumentOutOfRangeException- 인수 값이 호출된 메서드에 정의된 허용 가능한 값 범위를 벗어난 경우에만 예외 형식을 throw해야 합니다. 허용 범위를 AverageOfEvenNumberslowerBound명시적으로 정의하지는 않지만 upperBound 값은 lowerBound 허용 범위를 upperBound의미합니다.
    • InvalidOperationException: 예외 형식은 InvalidOperationException 메서드의 작동 조건이 특정 메서드 호출의 성공적인 완료를 지원하지 않는 경우에만 throw되어야 합니다. 이 경우 작동 조건은 메서드의 입력 매개 변수에 의해 설정됩니다.

    둘 이상의 예외 유형 중에서 선택할 수 있는 경우 문제에 더 잘 맞는 예외 유형을 선택합니다. 이 경우 두 예외 형식이 문제에 동일하게 정렬됩니다.

    문제에 동일하게 정렬된 두 개 이상의 예외 형식이 있는 경우 가장 좁은 범위의 예외 유형을 선택합니다. ArgumentOutOfRangeException 예외 형식은 메서드에 전달된 인수로 범위가 지정됩니다. InvalidOperationException 예외 유형은 메서드의 운영 조건으로 범위가 지정됩니다. 이 경우 ArgumentOutOfRangeException 예외 형식은 InvalidOperationException 예외 형식보다 범위가 더 좁습니다.

    AverageOfEvenNumbers 메서드는 ArgumentOutOfRangeException 예외를 throw해야 합니다.

  3. 메서드의 AverageOfEvenNumbers 상단에서 상한 문제를 확인하려면 다음과 같이 코드를 업데이트합니다.

    if (lowerBound >= upperBound)
    {
    
    }
    
    int sum = 0;    
    
  4. ArgumentOutOfRangeException 예외를 만들고 throw하려면 다음과 같이 if 코드 블록을 업데이트합니다.

    if (lowerBound >= upperBound)
    {
        throw new ArgumentOutOfRangeException("upperBound", "ArgumentOutOfRangeException: upper bound must be greater than lower bound.");
    }
    

    이 코드 줄은 예외 및 지정된 오류 메시지를 발생시키는 입력 매개 변수의 이름으로 클래스의 새 인스턴스 ArgumentOutOfRangeException 를 초기화합니다.

호출 코드에서 예외 catch

가능할 때마다 핸들할 수 있는 호출 스택 수준에서 예외를 catch해야 합니다. 이 샘플 애플리케이션에서 메서드의 매개 변수는 AverageOfEvenNumbers 호출 메서드(최상위 문)에서 관리할 수 있습니다.

  1. 최상위 진술까지 스크롤합니다.

  2. 코드 블록 내에 AverageOfEvenNumbers 메서드 호출 및 Console.WriteLine 문을 포함하려면 다음과 같이 코드를 업데이트합니다.

    try
    {
        // Calculate the sum of the even numbers between the bounds
        averageValue = AverageOfEvenNumbers(lowerBound, upperBound);
    
        // Display the result to the user
        Console.WriteLine($"The average of even numbers between {lowerBound} and {upperBound} is {averageValue}.");
    }
    
  3. 연결된 절을 catch 만들려면 다음 코드를 입력합니다.

    catch(ArgumentOutOfRangeException ex)
    {
    
    }
    
  4. 잠시 시간을 내어 예외를 처리하는 방법을 고려합니다.

    이 예외를 처리하려면 코드에서 다음을 수행해야 합니다.

    • 사용자에게 문제를 설명합니다.
    • 에 대한 upperBound새 값을 가져옵니다.
    • 새로운 AverageOfEvenNumbers을 사용하여 upperBound을(를) 호출합니다.
    • 제공된 새 catch가 여전히 upperBound보다 작거나 같으면 예외를 계속 lowerBound합니다.

    예외를 계속하려면 catch 루프가 필요합니다. AverageOfEvenNumbers 메서드를 최소한 한 번은 호출해야 하므로 do 루프를 사용해야 합니다.

  5. 루프 내부 trycatchdo 블록을 묶려면 다음과 같이 코드를 업데이트합니다.

    do
    {
        try
        {
            // Calculate the sum of the even numbers between the bounds
            averageValue = AverageOfEvenNumbers(lowerBound, upperBound);
    
            // Display the result to the user
            Console.WriteLine($"The average of even numbers between {lowerBound} and {upperBound} is {averageValue}.");
        }
        catch (ArgumentOutOfRangeException ex)
        {
    
        }
    }
    

    while 루프의 종료 조건을 정의하려면 식이 do 필요합니다. 코드 블록의 내용 do 이 정의되기 전에 조건을 지정하기 어렵습니다. catch 코드 블록을 완료하면, while 필요한 식을 정의하는 데 도움이 됩니다.

  6. 사용자에게 문제를 설명하고 새 upperBound를 받으려면, catch 코드 블록을 다음과 같이 업데이트하십시오.

    catch (ArgumentOutOfRangeException ex)
    {
        Console.WriteLine("An error has occurred.");
        Console.WriteLine(ex.Message);
        Console.WriteLine($"The upper bound must be greater than {lowerBound}");
        Console.Write($"Enter a new upper bound: ");
        upperBound = int.Parse(Console.ReadLine());
    }
    

    업데이트된 catch 코드 블록은 문제를 설명하고 사용자가 새 상한을 입력해야 합니다. 그러나 사용자에게 입력할 유효한 상한 값이 없으면 어떻게 해야 할까요? 사용자가 값을 입력하지 않고 루프를 종료해야 하는 경우 어떻게 해야 합니까?

  7. 사용자에게 새 상한을 입력하지 않고 루프를 종료하는 옵션을 제공하려면 다음과 같이 코드 블록을 업데이트 catch 합니다.

    catch (ArgumentOutOfRangeException ex)
    {
        Console.WriteLine("An error has occurred.");
        Console.WriteLine(ex.Message);
        Console.WriteLine($"The upper bound must be greater than {lowerBound}");
        Console.Write($"Enter a new upper bound (or enter Exit to quit): ");
        string? userResponse = Console.ReadLine();
        if (userResponse.ToLower().Contains("exit"))
        {
    
        }
        else
        {
            upperBound = int.Parse(userResponse);
        }
    }
    

    업데이트된 catch 코드 블록에는 "종료" 경로와 "새 상한" 경로라는 두 개의 경로가 포함됩니다.

  8. while 표현을 do 루프에 필요로 하는지 잠시 고려해 보세요.

    사용자가 프롬프트에서 "Exit"를 입력하면 코드가 루프를 종료해야 합니다. 사용자가 새 상한을 입력하는 경우 루프는 계속되어야 합니다. while 불리언을 평가하는 식을 사용할 수 있습니다. 다음은 그 예입니다.

    while (exit == false);
    

    제안된 while 식은 다음 동작을 설정합니다.

    • do 루프는 Boolean exitfalse와 같을 때까지 계속 반복됩니다.
    • do 루프는 exittrue과 같아지는 즉시 반복을 중지합니다.
  9. 부울 변수 exit을 인스턴스화하여, exit을 사용하여 do 루프의 종료 조건을 설정하려면 코드를 다음과 같이 업데이트하세요.

    bool exit = false;
    
    do
    {
        try
        {
            // Calculate the sum of the even numbers between the bounds
            averageValue = AverageOfEvenNumbers(lowerBound, upperBound);
    
            // Display the result to the user
            Console.WriteLine($"The average of even numbers between {lowerBound} and {upperBound} is {averageValue}.");
    
            exit = true;
        }
        catch (ArgumentOutOfRangeException ex)
        {
            Console.WriteLine("An error has occurred.");
            Console.WriteLine(ex.Message);
            Console.WriteLine($"The upper bound must be greater than {lowerBound}");
            Console.Write($"Enter a new upper bound (or enter Exit to quit): ");
            string? userResponse = Console.ReadLine();
            if (userResponse.ToLower().Contains("exit"))
            {
                exit = true;
            }
            else
            {
                exit = false;
                upperBound = int.Parse(userResponse);
            }
        }    
    } while (exit == false);
    
  10. 업데이트된 코드를 저장합니다.

  11. 실행 메뉴에서 디버깅 시작을 선택합니다.

  12. 터미널 패널로 전환합니다.

  13. “하한” 프롬프트에서 3을 입력합니다.

  14. “상한” 프롬프트에서 3을 입력합니다.

  15. 터미널 패널에 다음 출력이 표시됩니다.

    Enter the lower bound: 3
    Enter the upper bound: 3
    An error has occurred.
    ArgumentOutOfRangeException: upper bound must be greater than lower bound. (Parameter 'upperBound')
    The upper bound must be greater than 3
    Enter a new upper bound (or enter Exit to quit):
    
  16. 새 상한에 대한 프롬프트에서 11을 입력합니다.

  17. 터미널 패널에 다음 출력이 표시됩니다.

    Enter the lower bound: 3
    Enter the upper bound: 3
    An error has occurred.
    ArgumentOutOfRangeException: upper bound must be greater than lower bound. (Parameter 'upperBound')
    The upper bound must be greater than 3
    Enter a new upper bound (or enter Exit to quit): 11
    The average of even numbers between 3 and 11 is 7.
    
  18. 애플리케이션을 종료하려면 Enter 키를 누릅니다.

축하합니다! 예외를 성공적으로 throw, catch 및 핸들했습니다.

요약

이 단원에서 기억해야 하는 몇 가지 중요한 사항은 다음과 같습니다.

  • 애플리케이션 요구 사항을 지원하도록 디버그 환경이 구성되어 있는지 확인합니다.
  • 메서드 코드는 문제나 조건이 발생할 때 예외를 던져야 합니다.
  • 예외는 해결할 수 있는 호출 스택의 수준에서 잡혀야 합니다.