C #에서 예외를 잡아서 다시 던지는 이유는 무엇입니까?


557

직렬화 가능한 DTO 에 대한 기사 C #-데이터 전송 개체 를보고 있습니다.

이 기사에는 다음 코드가 포함되어 있습니다.

public static string SerializeDTO(DTO dto) {
    try {
        XmlSerializer xmlSer = new XmlSerializer(dto.GetType());
        StringWriter sWriter = new StringWriter();
        xmlSer.Serialize(sWriter, dto);
        return sWriter.ToString();
    }
    catch(Exception ex) {
        throw ex;
    }
}

이 기사의 나머지 부분은 제정신이며 합리적으로 보이지만 try-catch-throw는 WtfException을 발생시킵니다. 예외를 전혀 처리하지 않는 것과 정확히 같지 않습니까?

에르고 :

public static string SerializeDTO(DTO dto) {
    XmlSerializer xmlSer = new XmlSerializer(dto.GetType());
    StringWriter sWriter = new StringWriter();
    xmlSer.Serialize(sWriter, dto);
    return sWriter.ToString();
}

아니면 C #의 오류 처리에 대한 근본적인 내용이 누락 되었습니까? Java와 거의 동일하지만 (확인 된 예외 제외) 그렇지 않습니까? ... 즉, 둘 다 C ++을 개선했습니다.

스택 오버플로 질문 매개 변수가없는 캐치를 다시 던지는 것과 아무것도하지 않는 것의 차이점은 무엇입니까? try-catch-throw가 절대 안된다는 내 주장을지지하는 것 같습니다.


편집하다:

미래 에이 스레드를 찾는 사람을 요약하면 ...

하지 마라

try {
    // Do stuff that might throw an exception
}
catch (Exception e) {
    throw e; // This destroys the strack trace information!
}

스택 추적 정보는 문제의 근본 원인을 식별하는 데 중요 할 수 있습니다!

하다

try {
    // Do stuff that might throw an exception
}
catch (SqlException e) {
    // Log it
    if (e.ErrorCode != NO_ROW_ERROR) { // filter out NoDataFound.
        // Do special cleanup, like maybe closing the "dirty" database connection.
        throw; // This preserves the stack trace
    }
}
catch (IOException e) {
    // Log it
    throw;
}
catch (Exception e) {
    // Log it
    throw new DAOException("Excrement occurred", e); // wrapped & chained exceptions (just like java).
}
finally {
    // Normal clean goes here (like closing open files).
}

Java와 같이 덜 구체적인 예외보다 더 구체적인 예외를 포착하십시오.


참고 문헌 :


8
좋은 요약; finally 블록을 포함하기위한 추가 포인트.
Fredrik Mörk

"throw;"를 사용할 수 있다고 덧붙이고 싶습니다. "throw;"전에 e.Data 콜렉션의 메소드에 전송 된 매개 변수를 추가하여 더욱 유용합니다. 성명서
Michael Bahig

@MickTheWarMachineDesigner (및 시간제 화가). 응? Microshite Suckwell (아마도 2005 년 이후) 예외 처리에 대해 이야기하고 있습니다. 나는 일반적으로 예외 처리에 대해 이야기하고있었습니다. 그렇습니다. 나는이 4 년 전에이 글을 올린 이후에 약간을 배웠습니다. 그러나 네가 타당한 점이 있다고 고백하지만, 당신이 진짜 요점을 놓쳤다 고 생각합니다. 내 드리프트를 얻는다면? 이 질문은 C #에서 GENERALIZED 예외 처리에 관한 것입니다. 더 구체적으로 모든 종류의 예외를 다시 던지는 것에 대해. 멋있는?
corlettk

질문의 편집 요약 섹션을 자체 답변으로 옮기는 것을 고려하십시오. 이유 는 질문에서 자체 답변 편집질문에 포함 된 답변을 참조하십시오 .
DavidRR 2016

2
"배설이 발생했습니다"라는 부분을 아무도 보지 못했습니까? 코드가 똥을 넣은 것처럼 들립니다!
Jason Loki Smith

답변:


430

먼저; 기사의 코드가 수행하는 방식은 사악합니다. throw ex이 throw 문이있는 지점으로 예외의 호출 스택을 재설정합니다. 예외가 실제로 생성 된 위치에 대한 정보가 손실됩니다.

둘째, 당신이 그렇게 잡아서 다시 던지면, 부가 가치가 없다는 것을 알 수 있습니다. 위의 코드 예제 throw ex는 try-catch 없이도 좋을 것입니다 (또는 비트가 더 좋았습니다).

그러나 예외를 잡아서 다시 던지는 경우가 있습니다. 로깅은 다음 중 하나 일 수 있습니다.

try 
{
    // code that may throw exceptions    
}
catch(Exception ex) 
{
    // add error logging here
    throw;
}

6
@Fredrick, fyi (아마도 알고 있지만) 해당 ex객체 를 사용하지 않을 경우 인스턴스화 할 필요가 없습니다.
Eoin Campbell

78
@Eoin : 인스턴스화되지 않으면 기록하기가 다소 어렵습니다.
Sam Ax

30
네, "악"이 옳다고 생각합니다. 큰 코드에서 어딘가에 널 포인터 예외가 발생하는 경우를 고려하십시오. 메시지는 바닐라이며 스택 추적이 없으면 "어딘가에 null"이 남습니다. 생산이 종료되면 좋지 않습니다. flamin의 문제를 해결하는 데 몇 분도 걸리지 않으며 문제를 해결하거나 수정합니다 ... 예외 처리는 금의 무게만큼 가치가 있습니다.
corlettk

4
Java에서도 마찬가지입니까? "throw"와 "throw ex"?
JasonStoltz

8
@Jason, 이 질문을보십시오 . Java에서는 throw ex스택 추적을 다시 시작하지 않습니다.
Matthew Flaschen

117

이러지 마

try 
{
...
}
catch(Exception ex)
{
   throw ex;
}

스택 추적 정보가 손실됩니다 ...

어느 쪽이든

try { ... }
catch { throw; }

또는

try { ... }
catch (Exception ex)
{
    throw new Exception("My Custom Error Message", ex);
}

다시 던져야 할 이유 중 하나는 예를 들어 다른 예외를 처리하는 경우입니다.

try
{
   ...
}
catch(SQLException sex)
{
   //Do Custom Logging 
   //Don't throw exception - swallow it here
}
catch(OtherException oex)
{
   //Do something else
   throw new WrappedException("Other Exception occured");
}
catch
{
   System.Diagnostics.Debug.WriteLine("Eeep! an error, not to worry, will be handled higher up the call stack");
   throw; //Chuck everything else back up the stack
}

7
왜 캐치 {throw}를 모두 내버려 두지 않겠습니까?
AnthonyWJones 8:19에

3
catch {throw; } 특정 예외 유형 캐치 목록의 맨 아래에는 작성자가 해당 사례를 고려했음을 증명하지만 의견은 동일하게 충분할 수 있습니다. 코드를 읽을 때 추측하지 않는 것이 좋습니다.
annakata

87
어떤 이유로 SQLException의 이름이 나를 귀찮게합니다.
Michael Myers

13
그 catch (Exception) {throw new Exception (...)}은 예외 정보를 난독 화하고 예외 필터링이 불필요하게 콜 스택을 더 어렵게 만들기 때문에 절대로 절대로 해서는 안되는 일입니다 . 한 유형의 예외를 잡아서 다른 유형을 던져야하는 유일한 시점은 추상화 계층을 구현할 때 공급자 별 예외 유형 (예 : SqlException과 XmlException)을보다 일반적인 유형 (예 : DataLoadingException)으로 변환해야합니다.
jammycakes 12

3
@dark_perfect 메소드의 시작 부분에서 인수를 미리 확인하고 ArgumentNullException을 던져야합니다 (빠르게).
Andrei Bozantan

56

C # (C # 6 이전)은 VB가 수행하는 CIL "필터링 된 예외"를 지원하지 않으므로 C # 1-5에서 예외를 다시 발생시키는 한 가지 이유는 catch () 시점에 충분한 정보가 없기 때문입니다. 실제로 예외를 잡을 것인지 결정합니다.

예를 들어 VB에서는

Try
 ..
Catch Ex As MyException When Ex.ErrorCode = 123
 .. 
End Try

... 다른 ErrorCode 값으로 MyException을 처리하지 않습니다. v6 이전의 C #에서는 ErrorCode가 123이 아닌 경우 MyException을 포착하고 다시 발생시켜야합니다.

try 
{
   ...
}
catch(MyException ex)
{
    if (ex.ErrorCode != 123) throw;
    ...
}

C # 6.0부터 VB와 마찬가지로 필터링 할 수 있습니다 .

try 
{
  // Do stuff
} 
catch (Exception e) when (e.ErrorCode == 123456) // filter
{
  // Handle, other exceptions will be left alone and bubble up
}

2
데이브, 그러나 (적어도 자바에서는) "일반적인"MyException을 던지지 않을 것입니다. 특정 예외 유형을 정의하고 던져서 catch 블록에서 유형별로 차별화 할 수 있습니다 ...하지만 예 , 예외의 아키텍트 (여기서 JDBC의 SQLException (Java)를 다시 생각하고 있습니다.)가 역겹고 getErrorCode () 메소드를 노출시키는 경우 ... 흠 ... 당신은 요점을 알았습니다. .... 나는 가능한 건배 메이트 내가 당신의 시간을 주셔서 감사합니다 그것을 할 수있는 더 좋은 방법, 많은 키스 있다고 생각
corlettk

1
문제는 "C #에서 예외를 잡아서 다시 던지는 이유는 무엇입니까?"입니다. =] ... 특별한 예외가 있더라도 예외 필터는 의미가 있습니다. 예를 들어 SqlTimeoutException 및 SqlConnectionResetException (SqlException 모두)을 처리하는 경우를 고려하십시오. 예외 필터를 사용하면이 두 가지 중 하나 인 경우에만 SqlException을 포착 할 수 있으므로이 두 가지를 동일하게 처리하여 try / catch를 어지럽히는 대신 "ex가 SqlTimeoutException이거나 ex가 SqlConnectionResetException 인 경우 SqlException ex를 캐치"할 수 있습니다. (난 안 데이브 BTW 해요)
bzlm

3
C # 6에서 필터링 된 예외가 발생합니다!
Crispalot 경

14

다음과 같은 코드를 사용하는 주요 이유는 다음과 같습니다.

try
{
    //Some code
}
catch (Exception e)
{
    throw;
}

캐치에 중단 점을 가질 수 있도록 인스턴스화 된 예외 객체가 있습니다. 개발 / 디버깅하는 동안 나는 이것을 많이한다. 물론 컴파일러는 사용되지 않은 모든 e에 대해 경고를 제공하며 이상적으로는 릴리스 빌드 전에 제거해야합니다.

그래도 디버깅하는 동안 좋습니다.


1
그래, 난 그 일을 지불하지만, 그래, 당신은에 그것을보고 싶지 않을 것이다 게시 ERGO ... 코드 : 나는 ;-)을 게시 할 부끄러워 할 것
corlettk

25
실제로 이것은 필요하지 않습니다. Visual Studio에서는 예외가 발생할 때 디버거가 중단되도록 설정할 수 있으며 검사기 창에 예외 세부 정보가 표시됩니다.
jammycakes

8
디버깅 중 일부 코드 만 사용하려면 #if DEBUG ... #endif를 사용하면 이러한 행을 제거 할 필요가 없습니다.
Michael Freidgeim

1
나중에 몇 번이나했습니다. 매번 릴리스에서 벗어날 것입니다. @jammycakes Visual Studio의 예외에 대한 문제는 때로는 내가 원하는 예외가 유일한 예외 (또는 그 유형 중 하나)가 아니라는 것입니다. "예외로 건너 뛴 경우 중단"이있는 중단 점 조건을 여전히 알 수 없습니다. 그때까지 이것은 유용하게 남아있을 것입니다. 마이클 Freidgeim는 : #if DEBUG주위 둘다 try {} catch () {...}나 메스 꺼운 ... 사전 프로세서는 일반적으로 내 친구가 아니라 말하는하게, 솔직히, 조금 지저분합니다.

11

예외를 다시 던지는 유효한 이유는 예외에 정보를 추가하거나 원래 예외 중 하나를 원래 예외로 래핑하기 때문일 수 있습니다.

public static string SerializeDTO(DTO dto) {
  try {
      XmlSerializer xmlSer = new XmlSerializer(dto.GetType());
      StringWriter sWriter = new StringWriter();
      xmlSer.Serialize(sWriter, dto);
      return sWriter.ToString();
  }
  catch(Exception ex) {
    string message = 
      String.Format("Something went wrong serializing DTO {0}", DTO);
    throw new MyLibraryException(message, ex);
  }
}

감사합니다. 예외 예외 래핑 (특히 체인)은 완벽하게 제정신입니다. 제정신이 아닌 것은 예외를 잡아서 스택 트레이스를 빼내거나 더 악화시킬 수 있습니다.
corlettk

10

이것은 예외를 전혀 처리하지 않는 것과 정확히 같지 않습니까?

정확히는 같지 않습니다. 예외의 스택 추적을 재설정합니다. 나는 이것이 아마도 실수이므로 잘못된 코드의 예라는 것에 동의하지만.


8

당신은 ex를 던지고 싶지 않습니다-이것은 호출 스택을 잃을 것입니다. 예외 처리 (MSDN)를 참조하십시오 .

그리고 그렇습니다 .try ... catch는 유용한 정보를 제공하지 않습니다 (콜 스택을 잃어 버리는 것을 제외하고는-어떤 이유로 든이 정보를 노출시키지 않으려는 경우가 아니라면 실제로 더 나쁩니다).


throw ex를 사용할 때 전체 호출 스택을 잃지 않고 예외가 호출 스택보다 높은 지점에서 호출 스택의 일부를 잃습니다. 그러나 예외를 발생시킨 메소드에서 클라이언트가 호출 한 위치까지 호출 스택을 유지합니다. 실제로 사용하는 유스 케이스가 있거나 Microsoft의 훌륭한 직원이 허용하지 않은 경우가 있습니다. 즉, 나는 그것을 사용하지 않았습니다. 기억해야 할 또 다른 문제는 예외를 던지는 것이 비싸다는 것입니다. 매우 정당한 이유로 만 그렇게하십시오. 로깅 나는 정당화 될 수 있다고 생각합니다.
Charles Owen

5

사람들이 언급하지 않은 요점은 .NET 언어는 실제로 적절한 구별을하지 않지만 예외가 발생했을 때 조치취해야 하는지 여부와 문제를 해결 할지 여부에 대한 질문은 실제로 다른 질문이라는 것입니다. 예외를 기반으로 조치를 취해야하는 경우가 많지만 해결하려는 희망이 없으며 예외를 "해결"하는 데 필요한 모든 것이 스택을 특정 지점으로 풀어야하는 경우가 있습니다. 추가 조치가 필요하지 않습니다. .

우리가 처리 할 수있는 것만을 "잡아야"한다는 공통된 지혜 때문에 예외가 발생했을 때 조치를 취해야하는 많은 코드는 그렇지 않습니다. 예를 들어, 많은 코드는 잠금을 획득하고 보호 된 객체를 "일시적으로"불변을 위반하는 상태로 만든 다음 객체를 합법적 인 상태로 놓은 다음 다른 사람이 객체를 볼 수 있기 전에 잠금을 해제합니다. 객체가 위험한 상태에있는 동안 예외가 발생하면 일반적으로 해당 상태에있는 객체와 잠금을 해제하는 것이 일반적입니다. 객체가 "위험한"조건에있는 동안 예외가 발생하면 잠금이 명시 적으로 무효화되므로 나중에 더 이상이를 획득하려는 시도는 즉시 실패합니다.

대부분의 .NET 언어에서 예외를 기반으로 코드를 처리하는 유일한 방법은 예외 catch를 해결하지 않을 것임을 알고 있지만 문제의 조치를 수행 한 다음 다시 수행하는 것 throw입니다. 어떤 예외가 발생했는지에 대해 코드가 신경 쓰지 않을 경우 가능한 또 다른 방법 oktry/finally블록 과 함께 플래그 를 사용하는 것입니다 . ok플래그를 false블록 true앞, 블록이 끝나기 전 및 블록 안에 있는 플래그 앞에 설정하십시오 return. 그런 다음에 설정되지 않은 finally경우 ok예외가 발생했다고 가정합니다 . 이러한 접근 방식은 catch/ 보다 의미 상 낫지 만, throw추악하고 유지 관리가 쉽지 않습니다.


5

라이브러리 또는 dll에 대한 프로그래밍 기능을 수행 할 때 유용 할 수 있습니다.

이 rethrow 구조는 의도적으로 호출 스택을 재설정하여 함수 내부의 개별 함수에서 발생한 예외를 보는 대신 함수 자체에서 예외를 가져 오는 데 사용할 수 있습니다.

나는 이것이 던져진 예외가 더 깨끗하고 라이브러리의 "루트"에 들어 가지 않도록 사용되었다고 생각합니다.


3

catch-throw를 발생시키는 한 가지 이유는 스택에서 필터링이 더 깊이 발생하는 예외 필터 ( random old link ) 를 비활성화하는 것 입니다. 그러나 물론 그것이 의도라면, 거기에 의견이있을 것입니다.


나는 링크를 읽을 때까지 어디에서 무엇을 얻지 못했습니다 ... 그리고 나는 당신이 무엇을하고 있는지 정확히 모르겠습니다 ... 나는 VB.NET에 완전히 익숙하지 않습니다. 나는 그것이 "일관되지 않았다"고 합산되는 결과라고 생각한다. 그렇다. 나는 정적 메소드의 BIG 팬이다. 그것들이 단순하지 않고 코드에서 속성 설정을 분리하면 불일치의 가능성이 적다. 실제 작업을 수행합니다. 스택은 "자체 세척"입니다.
corlettk

3
사람들은 "try {Foo ();} finally {Bar ();}"라고 쓸 때 Foo와 Bar 사이에는 아무 것도 실행되지 않을 것으로 기대합니다. 그러나 이것은 사실이 아닙니다. 호출자가 예외 필터를 추가하고 중간에 'catch'가없고 Foo ()가 발생하면 마지막 (Bar)가 실행되기 전에 호출자의 다른 임의 코드가 실행됩니다. 변형이 없거나 보안이 강화 된 경우 이는 최종적으로 '즉시'정상적으로 복원 될 것으로 예상되며 다른 코드는 일시적인 변경을 볼 수 없습니다.
Brian

3

catch 블록에서 수행중인 작업과 호출 코드에 오류를 전달 하려는지 여부에 따라 다릅니다.

Catch io.FileNotFoundExeption ex대체 파일 경로 또는 이와 유사한 경로를 말하고 사용할 수는 있지만 여전히 오류가 발생합니다.

또한 Throw대신 수행 Throw Ex하면 전체 스택 추적을 유지할 수 있습니다. throw ex는 throw 문에서 스택 추적을 다시 시작합니다 (나는 그것이 의미가 있기를 바랍니다).


3

다른 많은 답변들이 예외를 다시 던지기를 원하는 이유에 대한 좋은 예를 제공하지만, '마지막'시나리오를 언급 한 사람은 없습니다.

예를 들어 커서를 설정하는 방법 (예 : 대기 커서)을 사용하는 방법이 있고이 방법에는 여러 개의 종료 점이 있습니다 (예 : if () return;). 방법의 끝.

이를 위해 모든 코드를 try / catch / finally로 랩핑 할 수 있습니다. 마지막으로 커서를 다시 오른쪽 커서로 설정하십시오. 유효한 예외를 묻지 않도록 캐치에서 다시 예외를 다시 던지십시오.

try
{
    Cursor.Current = Cursors.WaitCursor;
    // Test something
    if (testResult) return;
    // Do something else
}
catch
{
    throw;
}
finally
{
     Cursor.Current = Cursors.Default;
}

1
역사적 catch으로 의무적 인 부분 이었습니까 try...finally, 아니면이 예에서 기능적인 역할을합니까? -방금 확인한 try {} finally {}후 catch 블록없이 사용할 수 있습니다 .
Sebi

2

게시 한 코드의 예에서는 실제로 다시 잡을 수있는 캐치에 아무것도 수행되지 않으므로 예외를 포착 할 필요가 없습니다. 실제로 호출 스택이 손실되면 좋은 것보다 더 해가됩니다. .

그러나 예외가 발생하면 처리 할 호출 코드로 다시 던져야 할 경우 일부 논리 (예 : 파일 잠금의 SQL 연결 종료 또는 일부 로깅)를 수행하기 위해 예외를 잡을 수 있습니다. 비즈니스 계층을 구현하는 코더가 예외를 처리하도록하려면 프런트 엔드 코드보다 비즈니스 계층에서 더 일반적입니다.

게시 한 예제에서 예외를 포착 할 필요는 없지만 다시 반복하십시오. 그렇게하지 마십시오!


1

죄송하지만 "향상된 디자인"이라는 많은 사례는 여전히 끔찍한 냄새가 나거나 오해의 소지가 있습니다. {} catch {log; throw}는 전혀 의미가 없습니다. 예외 로깅은 응용 프로그램 내부의 중앙 위치에서 수행해야합니다. 어쨌든 예외가 스택 트레이스를 버블 링하는 이유는 무엇입니까?

컨텍스트 (예 : 하나의 예에서는 DTO)를 로그 메시지로 직렬화 할 때는주의해야합니다. 로그 파일에 액세스 할 수있는 모든 사람의 손에 닿기를 원하지 않는 민감한 정보를 쉽게 포함 할 수 있습니다. 그리고 예외에 새로운 정보를 추가하지 않으면 예외 래핑 지점이 실제로 보이지 않습니다. 좋은 오래된 Java에는 그 점이 있습니다. 호출자는 코드를 호출 할 때 어떤 종류의 예외를 예상해야하는지 알아야합니다. .NET에는이 기능이 없으므로 래핑은 내가 본 사례의 80 % 이상에서 아무런 효과가 없습니다.


당신의 생각 감사합니다 조. Java (및 C #에서는) 모든 예외 (체크되지 않은 예외 유형 포함)를 강제로 포착하거나 선언하도록 클래스 클래스 주석 @FaultBoundary를보고 싶습니다. 각 주석의 공용 인터페이스에서이 주석을 사용합니다. 따라서 @FaultBoundary ThingDAO 인터페이스는 SQLExceptions, NPE 또는 AIOB와 같은 구현 세부 정보를 유출 할 수 없습니다. 대신 "원인"stacktrace가 기록되고 DAOSystemException이 발생합니다 ... 시스템 예외를 "영구적으로 치명적"으로 정의합니다.
corlettk

5
잡아서 기록한 다음 다시 던질 이유가 많이 있습니다. 특히 캐치 로그가있는 방법에 정보가있는 경우 분석법을 벗어나면 손실됩니다. 오류는 나중에 처리되지만 기록되지 않을 수 있으며 시스템 결함에 대한 정보를 잃어 버렸습니다.
Andy

1
여기서는 Exception 클래스의 Data 속성이 유용한 곳으로 일반 로깅을 위해 모든 로컬 정보를 캡처합니다. 이 기사는 원래 내 관심을 끌었다 : blog.abodit.com/2010/03/…
McGuireV10

1

다른 사람들이 말한 것 외에도 catch 및 rethrowing이 no-op가 아니라는 것을 보여주는 관련 질문에 대한 내 대답 을 참조하십시오 (VB에는 있지만 일부 코드는 VB에서 C # 호출 될 수 있음).


이 링크가 질문에 대한 답변을 제공 할 수 있지만 여기에 답변의 필수 부분을 포함시키고 참조 용 링크를 제공하는 것이 좋습니다. 링크 된 페이지가 변경되면 링크 전용 답변이 유효하지 않을 수 있습니다. - 리뷰에서
LHIOUI

@ HamzaLH, 나는 그것이 잘 작성된 답변이 아니라는 것을 동의하지만 다른 답변과는 다른 정보와 긍정적 인 투표가 있습니다. 이해가 안되는데 왜 삭제를 제안합니까? "주제에 관한 짧은 답변과 해결책을 제시하는 것은 여전히 ​​답변입니다." 에서 meta.stackexchange.com/questions/226258/...
마이클 Freidgeim

이것은 링크 전용 답변입니다.
LHIOUI

1. 링크 전용 답변은 삭제하지 말고 주석으로 변경해야합니다. 2. 시간이 지남에 따라 깨질 가능성이 적은 외부 사이트가 아닌 다른 SO 질문에 대한 참조입니다. 참조 - 3. 그것은하지 "링크 전용"할 몇 가지 추가 설명이 meta.stackexchange.com/questions/225370/...을
마이클 Freidgeim

1

시나리오 catch-log-rethrow에 관한 대부분의 답변.

코드에서 코드를 작성하는 대신 OnExceptionOptions IncludeParameterValue 및 IncludeThisArgument와 함께 AOP, 특히 Postsharp.Diagnostic.Toolkit 을 사용하는 것이 좋습니다


이 링크가 질문에 대한 답변을 제공 할 수 있지만 여기에 답변의 필수 부분을 포함시키고 참조 용 링크를 제공하는 것이 좋습니다. 링크 된 페이지가 변경되면 링크 전용 답변이 유효하지 않을 수 있습니다. - 리뷰에서
Tony Dong

@TonyDong, 나는 그것이 잘 쓰여진 답변은 아니지만 다른 답변과는 다른 정보와 긍정적 인 투표 정보가 있음에 동의합니다. 이해가 안되는데 왜 삭제를 제안합니까? BTW, 5 년 후의 링크는 여전히 유효합니다. "주제에 관한 짧은 답변과 해결책을 제시하는 것은 여전히 ​​답변입니다." 에서 meta.stackexchange.com/questions/226258/...
마이클 Freidgeim

Stackoverflow에는이 제안 만 있습니다.
Tony Dong

@TonyDong, 대답이 전혀 쓸모가 없다면 "Looks OK"를 선택해야합니다
Michael Freidgeim

0

를 통해 예외를 다시 던지기 throw 것은 현재 예외를 처리 할 특정 코드가 없거나 특정 오류 사례를 처리 할 논리가 있지만 다른 모든 것을 건너 뛰고 싶은 경우에 유용합니다.

예:

string numberText = "";
try
{
    Console.Write("Enter an integer: ");
    numberText = Console.ReadLine();
    var result = int.Parse(numberText);

    Console.WriteLine("You entered {0}", result);
}
catch (FormatException)
{
    if (numberText.ToLowerInvariant() == "nothing")
    {
        Console.WriteLine("Please, please don't be lazy and enter a valid number next time.");
    }
    else
    {
        throw;
    }
}    
finally
{
    Console.WriteLine("Freed some resources.");
}
Console.ReadKey();

그러나 catch 블록에 조건절 을 사용하여이를 수행하는 다른 방법 도 있습니다 .

string numberText = "";
try
{
    Console.Write("Enter an integer: ");
    numberText = Console.ReadLine();
    var result = int.Parse(numberText);

    Console.WriteLine("You entered {0}", result);
}
catch (FormatException) when (numberText.ToLowerInvariant() == "nothing")
{
    Console.WriteLine("Please, please don't be lazy and enter a valid number next time.");
}    
finally
{
    Console.WriteLine("Freed some resources.");
}
Console.ReadKey();

이 메커니즘은 .NET 런타임이 예외 개체를 다시 던지기 전에 다시 작성하지 않아도되기 때문에 예외를 다시 던지는 것보다 효율적입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.