수색…


비고

관련 항목 :

예외 잡기

예외적 인 상황에서는 코드가 예외를 throw 할 수 있고 있어야합니다. 예를 들면 다음과 같습니다.

호출자는 이러한 예외를 "catch"하여 처리 할 수 ​​있으며 다음과 같은 경우에만 예외를 처리해야합니다.

  • 그것은 실제로 예외적 인 상황을 해결하거나 적절하게 회복 할 수 있습니다.
  • 예외를 다시 던져야하는 경우 유용 할 수있는 예외에 대한 추가 컨텍스트를 제공 할 수 있습니다 (다시 던져진 예외는 호출 스택 위로 예외 처리기에 의해 catch됩니다)

예외를 포착 하지 않으려 는 의도는 더 높은 수준에서 처리하려는 의도가있는 경우 완벽하게 유효하다는 점에 유의해야합니다.

예외를 잡는 것은 잠재적으로 던지는 코드를 try { ... } 블록에 다음과 같이 래핑하고 catch (ExceptionType) { ... } 블록에서 처리 할 수있는 예외를 포착하여 수행됩니다.

Console.Write("Please enter a filename: ");
string filename = Console.ReadLine();

Stream fileStream;

try
{
    fileStream = File.Open(filename);
}
catch (FileNotFoundException)
{
    Console.WriteLine("File '{0}' could not be found.", filename);
}

finally 블록 사용

try-finally 또는 try-catch-finallyfinally { ... } 블록은 예외가 발생했는지 여부에 관계없이 항상 실행됩니다 (예외 : StackOverflowException 이 throw되거나 Environment.FailFast() 가 호출 된 경우 제외 Environment.FailFast() ).

try { ... } 블록에서 획득 한 리소스를 안전하게 해제하거나 정리하는 데 사용할 수 있습니다.

Console.Write("Please enter a filename: ");
string filename = Console.ReadLine();

Stream fileStream = null;

try
{
    fileStream = File.Open(filename);
}
catch (FileNotFoundException)
{
    Console.WriteLine("File '{0}' could not be found.", filename);
}
finally
{
    if (fileStream != null)
    {
        fileStream.Dispose();
    }
}

catch 된 예외를 잡아서 재실행

예외를 잡아서 무언가를하고 싶지만 예외로 인해 현재 코드 블록을 계속 실행할 수없는 경우 호출 스택의 다음 예외 처리기로 예외를 다시 throw해야 할 수 있습니다. 이것을하기위한 좋은 방법과 나쁜 방법이 있습니다.

private static void AskTheUltimateQuestion()
{
    try
    {
        var x = 42;
        var y = x / (x - x); // will throw a DivideByZeroException

        // IMPORTANT NOTE: the error in following string format IS intentional
        // and exists to throw an exception to the FormatException catch, below
        Console.WriteLine("The secret to life, the universe, and everything is {1}", y); 
    }
    catch (DivideByZeroException)
    {
        // we do not need a reference to the exception
        Console.WriteLine("Dividing by zero would destroy the universe.");

        // do this to preserve the stack trace:
        throw;
    }
    catch (FormatException ex)
    {
        // only do this if you need to change the type of the Exception to be thrown 
        // and wrap the inner Exception

        // remember that the stack trace of the outer Exception will point to the
        // next line

        // you'll need to examine the InnerException property to get the stack trace
        // to the line that actually started the problem

        throw new InvalidOperationException("Watch your format string indexes.", ex);
    }
    catch (Exception ex)
    {
        Console.WriteLine("Something else horrible happened. The exception: " + ex.Message);

        // do not do this, because the stack trace will be changed to point to
        // this location instead of the location where the exception
        // was originally thrown:
        throw ex; 
    }
}

static void Main()
{
    try
    {
        AskTheUltimateQuestion();
    }
    catch
    {
        // choose this kind of catch if you don't need any information about 
        // the exception that was caught

        // this block "eats" all exceptions instead of rethrowing them
    }
}

예외 유형 및 심지어 예외 속성 (C # 6.0의 새로운 기능, VB.NET에서 좀 더 긴 (인용문 필요))을 기준으로 필터링 할 수 있습니다.

문서 / C # / 새로운 기능

예외 필터

C # 6.0 예외는 when 연산자를 사용하여 필터링 할 수 있습니다.

이는 간단한 if 를 사용하는 것과 비슷하지만 when 의 조건이 충족되지 않으면 스택을 풀지 않습니다.

try
{ 
  // ...
}
catch (Exception e) when (e.InnerException != null) // Any condition can go in here.
{
  // ...
}

동일한 정보는 C # 6.0 기능 에서 찾을 수 있습니다 : 예외 필터

catch 블록 내에서 예외 재발행

catch 블록 내에서 throw 키워드는 예외 값을 지정하지 않고 자체적으로 사용되어 방금 포착 된 예외를 다시 throw 합니다. 예외를 반환하면 원래 예외가 예외 처리 체인을 계속하여 호출 스택이나 관련 데이터를 보존합니다.

try {...}
catch (Exception ex) {
  // Note: the ex variable is *not* used
  throw;
}

일반적인 안티 패턴은 throw exthrow ex 스택 트레이스에 대한 다음 예외 처리기의 뷰를 제한하는 효과가 있습니다.

try {...}
catch (Exception ex) {
  // Note: the ex variable is thrown
  //  future stack traces of the exception will not see prior calls
  throw ex;  
}

일반적으로 사용 throw ex 스택 추적을 검사 미래의 예외 핸들러 만까지 거슬러 통화를 볼 수있을 것 같은 바람직하지 않다 throw ex . ex 변수를 생략하고 throw 키워드 만 사용하면 원래 예외가 "버블 업" 됩니다.

정보를 유지하면서 다른 메소드에서 예외를 던집니다.

때때로 예외를 잡아서 원래의 예외 스택을 유지하면서 다른 스레드 나 메소드에서 던져 버리기를 원할 수도 있습니다. ExceptionDispatchInfo 사용 ExceptionDispatchInfo 작업을 수행 할 수 있습니다.

using System.Runtime.ExceptionServices;

void Main()
{
    ExceptionDispatchInfo capturedException = null;
    try
    {
        throw new Exception();
    }
    catch (Exception ex)
    {
        capturedException = ExceptionDispatchInfo.Capture(ex);
    }
    
    Foo(capturedException);
}

void Foo(ExceptionDispatchInfo exceptionDispatchInfo)
{
    // Do stuff

    if (capturedException != null)
    {
        // Exception stack trace will show it was thrown from Main() and not from Foo()
        exceptionDispatchInfo.Throw();
    }
}


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow