답변:
구조
try { ... }
catch () { ... } /* You can even omit the () here */
try { ... }
catch (Exception e) { ... }
둘 다 블록 내부에서 발생하는 모든 예외 를 포착한다는 점에서 비슷 합니다 try
(이를 사용하여 예외를 기록하는 데 사용하지 않는 한 피해야합니다 ). 이제 이것들을보세요 :
try { ... }
catch ()
{
/* ... */
throw;
}
try { ... }
catch (Exception e)
{
/* ... */
throw;
}
try { ... }
catch (Exception e)
{
/* ... */
throw e;
}
첫 번째와 두 번째 try-catch 블록은 똑같습니다. 단순히 현재 예외를 다시 던지고 해당 예외가 "소스"와 스택 추적을 유지합니다.
세 번째 try-catch 블록은 다릅니다. 예외가 발생하면 소스와 스택 추적이 변경되어 throw e
해당 try-catch 블록을 포함하는 메서드의 바로 그 줄에서이 메서드에서 예외가 throw 된 것처럼 보입니다 .
어느 것을 사용해야합니까? 각 경우에 따라 다릅니다.
데이터베이스에 유지 Person
하는 .Save()
메서드 가있는 클래스 가 있다고 가정 해 보겠습니다 . 애플리케이션이 Person.Save()
어딘가 에서 메서드를 실행한다고 가정 해 보겠습니다 . DB가 Person 저장을 거부 .Save()
하면 예외가 발생합니다. 당신이 사용해야 throw
또는throw e
이 경우에 ? 음, 상황에 따라 다릅니다.
내가 선호하는 것은 다음과 같습니다.
try {
/* ... */
person.Save();
}
catch(DBException e) {
throw new InvalidPersonException(
"The person has an invalid state and could not be saved!",
e);
}
이것은 DBException을 던지는 새로운 예외의 "내부 예외"로 넣어야합니다. 따라서이 InvalidPersonException을 검사 할 때 스택 추적에는 Save 메서드에 대한 정보가 포함되지만 (문제를 해결하는 데 충분할 수 있음) 필요한 경우 원래 예외에 계속 액세스 할 수 있습니다.
마지막으로, 예외를 예상 할 때 일반적인 예외가 아닌 특정 예외를 실제로 포착해야합니다 Exception
. 즉, InvalidPersonException이 예상되는 경우 다음을 선호해야합니다.
try { ... }
catch (InvalidPersonException e) { ... }
에
try { ... }
catch (Exception e) { ... }
행운을 빕니다!
첫 번째는 스택 추적을 보존하고 두 번째는 재설정합니다. 즉, 두 번째 접근 방식을 사용하면 예외의 스택 추적이 항상이 메서드에서 시작되며 예외의 원래 원인을 찾지 못하므로 예외 로그를 읽는 사람에게 재앙이 될 수있는 원래 예외 추적을 잃게됩니다. .
두 번째 방법은 스택 추적에 추가 정보를 추가하려는 경우 유용 할 수 있지만 다음과 같이 사용됩니다.
try
{
// do something
}
catch (Exception ex)
{
throw new Exception("Additional information...", ex);
}
차이점을 논의 하는 블로그 게시물 이 있습니다.
throw
대 throw e
.
매개 변수없는 catch와 a의 차이점 catch(Exception e)
은 예외에 대한 참조를 얻는다는 것입니다. 프레임 워크 버전 2에서 관리되지 않는 예외는 관리되는 예외로 래핑되므로 매개 변수없는 예외는 더 이상 어떤 경우에도 유용하지 않습니다.
차이 throw;
와 throw e;
상기 제 하나의 예외를 다시 발생하는 데 사용되며, 두 번째는 새로 생성 된 예외를 발생하기 위해 사용된다는 점이다. 두 번째 예외를 사용하여 예외를 다시 발생 시키면 새 예외로 처리하고 원래 발생했던 모든 스택 정보를 대체합니다.
따라서 질문의 대안 중 하나를 사용하지 마십시오. 매개 변수없는 catch를 사용해서는 안되며 throw;
예외를 다시 발생시키는 데 를 사용해야합니다 .
또한 대부분의 경우 모든 예외에 대해 기본 클래스보다 더 구체적인 예외 클래스를 사용해야합니다. 예상되는 예외 만 포착해야합니다.
try {
...
} catch (IOException e) {
...
throw;
}
예외를 다시 던질 때 정보를 추가하려면 모든 정보를 보존하기 위해 원래 예외를 내부 예외로 사용하여 새 예외를 생성합니다.
try {
...
} catch (IOException e) {
...
throw new ApplicationException("Some informative error message", e);
}