수색…
비고
관련 항목 :
예외 잡기
예외적 인 상황에서는 코드가 예외를 throw 할 수 있고 있어야합니다. 예를 들면 다음과 같습니다.
- 스트림의 끝을지나 읽으 려고 시도 합니다.
- 파일에 액세스하는 데 필요한 권한 이 없습니다.
- 0 으로 나누기 와 같이 잘못된 연산을 수행하려고했습니다.
- 인터넷에서 파일을 다운로드 할 때 발생하는 시간 초과
호출자는 이러한 예외를 "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-finally
의 finally { ... }
블록은 예외가 발생했는지 여부에 관계없이 항상 실행됩니다 (예외 : 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 # 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 ex
를 throw 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();
}
}