try / catch / throw와 try / catch (e) / throw e의 차이점


103

차이점은 무엇입니까

try { }
catch
{ throw; }

try { }
catch(Exception e)
{ throw e;}

?

그리고 언제 둘 중 하나를 사용해야합니까?

답변:


151

구조

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) { ... }

행운을 빕니다!


34

첫 번째는 스택 추적을 보존하고 두 번째는 재설정합니다. 즉, 두 번째 접근 방식을 사용하면 예외의 스택 추적이 항상이 메서드에서 시작되며 예외의 원래 원인을 찾지 못하므로 예외 로그를 ​​읽는 사람에게 재앙이 될 수있는 원래 예외 추적을 잃게됩니다. .

두 번째 방법은 스택 추적에 추가 정보를 추가하려는 경우 유용 할 수 있지만 다음과 같이 사용됩니다.

try
{
    // do something
}
catch (Exception ex)
{
    throw new Exception("Additional information...", ex);
}

차이점을 논의 하는 블로그 게시물 이 있습니다.


알아두면 좋은 것입니다!
Myles

그래서 왜 두 번째를 사용합니까? 첫 번째 만 사용하는 것이 더 낫습니까?
Karim

1
두 번째는 특정 예외를 확인해야 할 때 유용합니다. OutOfRangeException이 떠오르거나 메시지를 기록해야하는 경우 등입니다. 첫 번째는 try {} catch (...) {}와 유사한 와일드 카드 예외 처리기 인 것 같습니다. C ++에서.
3Dave 2009

1
David, 그것은 catch (Exception e) 부분 에만 적용됩니다 . 그리고 그 분리되어 throwthrow e.
Henk Holterman

6

당신은 사용해야합니다

try { }
catch(Exception e)
{ throw }

다시 던지기 전에 예외로 무언가를하고 싶은 경우 (예 : 로깅). 외로운 던지기는 스택 추적을 유지합니다.


여기서 "throw"를 "throw e"로 바꾸면 어떻게됩니까?
Karim

5

매개 변수없는 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);
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.