차이점은 무엇입니까
try { ... }
catch{ throw }
과
try{ ... }
catch(Exception e) {throw new Exception(e.message) }
두 번째 메시지에 상관없이?
차이점은 무엇입니까
try { ... }
catch{ throw }
과
try{ ... }
catch(Exception e) {throw new Exception(e.message) }
두 번째 메시지에 상관없이?
답변:
throw; 원래 예외를 다시 발생시키고 원래 스택 추적을 유지합니다.
throw ex;원래 예외를 throw하지만 스택 추적을 재설정하여 catch블록 까지 모든 스택 추적 정보를 삭제합니다 .
throw ex;throw new Exception(ex.Message);더 나빠요 Exception예외의 원래 스택 추적과 유형을 잃어 버린 새로운 인스턴스를 만듭니다 . (예 :) IOException.
또한 일부 예외에는 추가 정보 (예 :)가 ArgumentException.ParamName있습니다.
throw new Exception(ex.Message); 이 정보도 파괴됩니다.
경우에 따라 예외가 발생했을 때 코드가 수행 한 작업에 대한 추가 정보를 제공 할 수 있도록 모든 예외를 사용자 정의 예외 오브젝트로 랩핑 할 수 있습니다.
이렇게하려면 상속을하는 새로운 클래스를 정의 Exception, 네 예외 생성자를 추가 및 소요 선택적으로 추가 생성자 InnerException추가 정보뿐만 아니라,하고, 새로운 예외 클래스를 던져 통과 ex는 AS InnerException매개 변수 . original를 전달하면 InnerException스택 추적을 포함하여 모든 원래 예외 속성이 유지됩니다.
throw new MyCustomException(myMessage, ex);물론.
ex.Message하는 것입니다 악화.
[Serializable()]합니다.
throw;예외가 발생한 실제 줄 번호가 줄 번호로 바뀝니다 throw;. 어떻게 처리 할 것을 제안합니까? stackoverflow.com/questions/2493779/…
첫 번째는 원래 스택 추적을 유지합니다.
try { ... }
catch
{
// Do something.
throw;
}
두 번째는 예외 유형 및 / 또는 메시지 및 기타 데이터를 변경할 수 있습니다.
try { ... } catch (Exception e)
{
throw new BarException("Something broke!");
}
내부 예외를 전달하는 세 번째 방법도 있습니다.
try { ... }
catch (FooException e) {
throw new BarException("foo", e);
}
다음을 사용하는 것이 좋습니다.
다른 사람이 보지 못한 한 가지 다른 점은 다음과 같습니다.
catch {} 블록에서 아무 것도하지 않으면 try ... catch를 갖는 것은 의미가 없습니다. 나는 항상 이것을 본다 :
try
{
//Code here
}
catch
{
throw;
}
또는 더 나쁜 :
try
{
//Code here
}
catch(Exception ex)
{
throw ex;
}
최악의 경우 :
try
{
//Code here
}
catch(Exception ex)
{
throw new System.Exception(ex.Message);
}
throw발견 된 예외 throw new Exception의 세부 사항 중 일부 를 잃으면 서 스택 추적을 유지하면서 발견 된 예외를 다시 발생시킵니다.
일반적으로 throw그 시점에서 예외를 완전히 처리하지 않고 자체적으로 예외를 기록합니다.
BlackWasp에는 C #에서 Throwing Exceptions 라는 제목의 기사가 있습니다.
두 번째 예는 예외의 스택 추적을 재설정합니다. 첫 번째는 예외의 기원을 가장 정확하게 유지합니다. 또한 실제로 잘못 된 것을 아는 데 핵심적인 원래 유형의 포장을 풀었습니다 ... 기능에 두 번째가 필요한 경우-예를 들어 확장 정보를 추가하거나 사용자 정의 'HandleableException'과 같은 특수 유형으로 다시 줄 바꿈하려면 InnerException 속성도 설정되어 있는지 확인하십시오!
가장 중요한 차이점은 두 번째 표현식이 예외 유형을 지우는 것입니다. 예외 유형은 예외를 포착하는 데 중요한 역할을합니다.
public void MyMethod ()
{
// both can throw IOException
try { foo(); } catch { throw; }
try { bar(); } catch(E) {throw new Exception(E.message); }
}
(...)
try {
MyMethod ();
} catch (IOException ex) {
Console.WriteLine ("Error with I/O"); // [1]
} catch (Exception ex) {
Console.WriteLine ("Other error"); // [2]
}
경우 foo()가 발생 IOException, [1]catch 블록은 예외를 잡을 것입니다. 그러나 bar()던질 때 캐치 블록에 잡히지 않는 IOException일반 Exception개미 로 변환됩니다 [1].
던지기 또는 던지기 ex는 단순히 오류 정보를 기록하고 호출자에게 정보를 다시 보내지 않으려는 경우 예외를 던지거나 다시 던지는 데 사용됩니다. 그러나 throw 또는 throw ex를 사용하는 호출자에게 예외에 대한 의미있는 정보를 보내려는 경우를 대비하십시오. 이제 throw와 throw ex의 차이점은 throw는 스택 추적과 다른 정보를 유지하지만 throw ex는 새로운 예외 객체를 생성하여 원래 스택 추적이 손실된다는 것입니다. 따라서 throw and throw e를 사용해야하는 경우에도 여전히 호출 스택 정보를 재설정하는 것과 같은 예외를 다시 발생시켜야하는 상황이 몇 가지 있습니다. 예를 들어, 메소드가 라이브러리에 있고 호출 코드에서 라이브러리의 세부 사항을 숨기려면 호출 스택에 라이브러리 내의 개인용 메소드에 대한 정보를 포함시키지 않아도됩니다. 이 경우 라이브러리의 공개 메소드에서 예외를 포착 한 다음 다시 호출하여 호출 스택이 해당 공개 메소드에서 시작되도록 할 수 있습니다.
여기에 어떤 대답도 차이를 보여주지 않으므로 차이를 이해하는 데 어려움을 겪는 사람들에게 도움이 될 수 있습니다. 이 샘플 코드를 고려하십시오.
using System;
using System.Collections.Generic;
namespace ExceptionDemo
{
class Program
{
static void Main(string[] args)
{
void fail()
{
(null as string).Trim();
}
void bareThrow()
{
try
{
fail();
}
catch (Exception e)
{
throw;
}
}
void rethrow()
{
try
{
fail();
}
catch (Exception e)
{
throw e;
}
}
void innerThrow()
{
try
{
fail();
}
catch (Exception e)
{
throw new Exception("outer", e);
}
}
var cases = new Dictionary<string, Action>()
{
{ "Bare Throw:", bareThrow },
{ "Rethrow", rethrow },
{ "Inner Throw", innerThrow }
};
foreach (var c in cases)
{
Console.WriteLine(c.Key);
Console.WriteLine(new string('-', 40));
try
{
c.Value();
} catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
}
}
}
다음과 같은 출력이 생성됩니다.
Bare Throw:
----------------------------------------
System.NullReferenceException: Object reference not set to an instance of an object.
at ExceptionDemo.Program.<Main>g__fail|0_0() in C:\...\ExceptionDemo\Program.cs:line 12
at ExceptionDemo.Program.<>c.<Main>g__bareThrow|0_1() in C:\...\ExceptionDemo\Program.cs:line 19
at ExceptionDemo.Program.Main(String[] args) in C:\...\ExceptionDemo\Program.cs:line 64
Rethrow
----------------------------------------
System.NullReferenceException: Object reference not set to an instance of an object.
at ExceptionDemo.Program.<>c.<Main>g__rethrow|0_2() in C:\...\ExceptionDemo\Program.cs:line 35
at ExceptionDemo.Program.Main(String[] args) in C:\...\ExceptionDemo\Program.cs:line 64
Inner Throw
----------------------------------------
System.Exception: outer ---> System.NullReferenceException: Object reference not set to an instance of an object.
at ExceptionDemo.Program.<Main>g__fail|0_0() in C:\...\ExceptionDemo\Program.cs:line 12
at ExceptionDemo.Program.<>c.<Main>g__innerThrow|0_3() in C:\...\ExceptionDemo\Program.cs:line 43
--- End of inner exception stack trace ---
at ExceptionDemo.Program.<>c.<Main>g__innerThrow|0_3() in C:\...\ExceptionDemo\Program.cs:line 47
at ExceptionDemo.Program.Main(String[] args) in C:\...\ExceptionDemo\Program.cs:line 64
이전 답변에서 알 수 있듯이 베어 스로우는 실패한 원래 코드 줄 (12 행)과 예외가 발생했을 때 호출 스택에서 활성화 된 다른 두 지점 (행 19 및 64)을 명확하게 보여줍니다.
다시 던지기 사례의 결과는 왜 문제인지 보여줍니다. 이와 같이 예외가 다시 발생하면 예외에는 원래 스택 정보가 포함되지 않습니다. 만 유의 throw e(라인 35) 및 최 호출 스택 포인트 (라인 64)가 포함된다. 이런 식으로 예외를 throw하면 fail () 메서드를 문제의 원인으로 추적하기가 어려울 수 있습니다.
마지막 경우 (innerThrow)는 가장 정교하며 위의 것보다 많은 정보를 포함합니다. 새 예외를 인스턴스화하고 있으므로 컨텍스트 정보 ( "외부"메시지를 추가 할 수 있지만 새 예외의 .Data 사전에 추가 할 수 있음)를 추가하고 원본의 모든 정보를 보존 할 수 있습니다. 예외 (도움말 링크, 데이터 사전 등 포함).