2009-09-21 5 views
5

.NET 프로그래밍 가이드 라인에는 일반적인 예외는 발견하지 않아야한다고 명시되어 있습니다. 경우에 다른 내가 특정 예외는 아니지만 그들 모두와 나는 예외를 다시 던질 잡을 다음 코드에서.NET Catch 일반 예외

private object CreateObject(string classname) 
    { 
     object obj = null; 
     if (!string.IsNullOrEmpty(classname)) 
     { 
      try 
      { 
       System.Type oType = System.Type.GetTypeFromProgID(customClass); 
       obj = System.Activator.CreateInstance(oType); 
      } 
      catch (Exception ex) 
      { 
       Log.Error("Unable to create instance for COM Object with class name " + classname + "\n" + ex.Message); 
      } 
     } 
     return obj; 
    } 

: 다음 코드 때문에 일반 예외 유형 캐치의 매우 좋지 않아 가정 비 제네릭 예외 그러나 "CreateInstance"함수는 많은 예외 (ArgumentNullException, ArgumentException, NotSupportedException, TargetInvocationException, MethodAccessException, MemberAccessException, InvalidComObjectException, MissingMethodException, COMException, TypeLoadException)를 throw 할 수 있습니다.

다른 모든 개별 예외를 포착해도됩니까? 아니면 더 좋은 방법이 있습니까?

private object CreateObject(string classname) 
    { 
     object obj = null; 
     if (!string.IsNullOrEmpty(classname)) 
     { 
      try 
      { 
       System.Type oType = System.Type.GetTypeFromProgID(customClass); 
       obj = System.Activator.CreateInstance(oType); 
      } 
      catch (NotSupportedException ex) 
      { 
       Log.Error("...." + ex.Message); 
      } 
      catch (TargetInvocationException ex) 
      { 
       Log.Error("...." + ex.Message); 
      } 
      catch (COMException ex) 
      { 
       Log.Error("...." + ex.Message); 
      } 
      catch (TypeLoadException ex) 
      { 
       Log.Error("...." + ex.Message); 
      } 
      catch (InvalidComObjectException ex) 
      { 
       Log.Error("...." + ex.Message); 
      } 
      catch (Exception ex) 
      { 
       Log.Error("Unable to create instance for COM Object with class name " + classname + "\n" + ex.Message); 
       throw; 
      } 
     } 
     return obj; 
    } 
+0

중복 : http://stackoverflow.com/questions/204814/is-there-any-valid-reason-to-ever-ignore-a-caught-exception –

답변

9

.NET Framework 2 이상의 프레임 워크에서는 일반적인 예외를 포착하는 것이 좋습니다.

- 편집

다른 제외하고 다른 일을 할 수 있다면 당신이하지입니다 것이 유일한 이유. 그것들을 모두 다룰 계획이라면, 장군 (또는 당신이 한 특정자를 붙잡고 다른 어떤 사람이 올라 가게하십시오)을 잡으십시오.

+3

동의합니다. 때로는 극단에 대한 일반적인 예외를 포착하지 않기 위해이 작업을 수행한다고 생각합니다. –

+5

나는 동의하지 않는다. 이것은 귀하의 신청서를 예외적 인 상태로 남겨 둘 것입니다. 당신은 당신이 뭔가를 할 수있는 예외만을 처리해야합니다. 간단하게 로깅하고 계속 진행하는 것은 나쁜 생각입니다. –

+0

@ justin.m.chase : 매우 이상한 입장입니다. 따라서 앱이 다운 될 때마다 사용자에게 .net 일반 오류 페이지가 표시되는 것을 선호하게됩니다. –

1

모든 예외를 catch하여 문제를 가로 채고 무서운 스택 출력이 아닌 사용자에게 친숙한 메시지를 표시하는 것이 좋습니다.

예외를 삼키지 않고 로그에 남기고 백그라운드에서 적절하게 반응하는 한.

1

다른 예외 유형으로 특별한 작업을 수행하려는 경우 별도의 catch 블록에서 예외를 catch하십시오. 그렇지 않으면 별도로 기록하는 것이 의미가 없습니다.

1

우리가 일반적으로 예외 그러나 가이드 라인을 사용하지 않아야 엄격한 규칙이 없다 우리가 일반적인 예외 가지 말았어야 예외의 특정 유형을 처리 할 수있는 옵션이 ...있을 때마다

우리가 확실하다면 말한다 모든 예외는 동일한 방식으로 처리되고 다음 일반 예외를 사용합니다. 그렇지 않으면 각각의 모든 예외에 대해 처리하고 제네릭은 알 수없는 예외에 대해 마지막으로 와야합니다 ..

및 때로는 응용 프로그램에 예외가 발생합니다 특정 예외 처리로 인해 코드에서 처리되면 응용 프로그램이 충돌 할 수 있습니다.

더 나은 접근법은 모든 특정 예외를 처리 한 다음 응용 프로그램이 충돌없이 안정적으로 유지되도록 일반 예외에 대한 모서리를 제공합니다.

이러한 불필요한 일반 예외는 향후 버전 개선을 위해보고되거나 기록 될 수 있습니다 ... 당신이하지 않는 예외를 잡을 안 일반적으로

11

: 당신은 당신이 처리하고 대해 뭔가를 할 수있는 고유의 예외가

  1. 합니다. 그러나이 경우에는 처음부터 예외를 고려하고 회피하지 말아야하는지 여부를 항상 확인해야합니다.

  2. 응용 프로그램 (예 : UI)의 최상위 수준에 있으며 기본 동작을 사용자에게 표시하지 않으려합니다. 예를 들어, "please send us log"스타일 메시지가있는 오류 대화 상자가 필요할 수 있습니다.

  3. DB 트랜잭션을 롤백하는 경우와 같이 어떻게 든 처리 한 후에 예외를 다시 throw합니다.

이 예제에서 왜 이러한 모든 유형을 포착하고 있습니까? 당신의 코드가 단지 수 있다는 것을 나에게 보인다

try 
{ 
    System.Type oType = System.Type.GetTypeFromProgID(customClass); 
    return System.Activator.CreateInstance(oType); 
} 
catch (Exception ex) 
{ 
    Log.Error("...." + ex.Message); 

    //the generic catch is always fine if you then do this: 
    throw; 
} 

그래서 문제는 규칙의 예입니다 (3) - 당신이 예외를 기록 할, 그러나 계속 위로 그것을 던져.

모든 다른 유형이 있으므로 어떤 경우에는 처리 할 수 ​​있음을 알 수 있습니다 (사례 1). 예를 들어 당신이 주변에 COMException 작동하는 관리되지 않는 통화가 있음을 알고 있다고 가정 - 다음 코드가된다 :

try 
{ 
    System.Type oType = System.Type.GetTypeFromProgID(customClass); 
    return System.Activator.CreateInstance(oType); 
} 
catch (COMException cex) 
{ //deal with special case: 
    return LoadUnmanaged(); 
} 
catch (Exception ex) 
{ 
    Log.Error("...." + ex.Message); 

    //the generic catch is always fine if you then do this: 
    throw; 
} 
+0

나는 이러한 모든 종류의 예외가 발생할 수 있기 때문에 (예를 들어, 사용이 지원되지 않거나 올바르게 등록되지 않은 클래스 이름을 전달할 수 있기 때문에) 예외가 발생하면 사전에 예외를 검사 할 수있는 좋은 방법이 없습니다. ArgumentNullException을 확인할 수 있습니다. – Ioannis

+0

나는 그것들이 모두 일어날 수 있다고 확신하지만, 예외 타입에 특정한 것을하지 않는다면, 일반적인'Exception'을 잡아 내고 그것을 버리는 것이 더 낫다. – Keith

+1

이 답변은 정확합니다. 핵심은 당신이 그들을 삼키지 않는 일반적인 예외를 던지고 있다는 것입니다. –

1

그것은 가능성을 보여주기 때문에 처리 오류를 처리 할 때 습관적으로 기본 Exception을 잡으려고 가난한 연습 간주 당신이 실제로 무엇을 다루고 있는지에 대한 이해 부족. 코드 블록을 보았을 때 Exception의 내용은 "여기에 문제가 생기면 무엇이든 할 수 있습니다."라고 말하면서 무엇이든 NullReferenceException에서 OutOfMemoryException으로 바뀔 수 있습니다.

모든 오류를 동일하게 취급 할 때의 위험은 오류의 심각도 또는 오류 해결 방법에 대해 신경 쓰지 않는다는 것을 의미합니다. 99 %는 코드 catch(Exception ex)을 볼 때 즉시 예외가 발생하는 코드가 뒤따 랐기 때문에 실제로 명령문이 실패한 이유를 알 수 없습니다. 응.

오류 로깅의 예는 응용 프로그램의 최상위 수준에서 모든 예외를 처리하려는 순수한 상황에서 추악한 응용 프로그램 종료를 막기 위해 기본 Exception을 사용하는 올바른 방법을 보여줍니다 음식물.

1

키이스의 답변에 동의합니다. 두 코드 예제의 실제 문제점은 null을 반환 할 수 있다는 것입니다. Object 유형의 인스턴스를 반환하는 CreateObject라는 메서드가 있습니다. 이 메서드는 COMException 같은 어떤 이유로 실패했습니다. 두 코드 예제는 모두 null을 반환합니다. 호출 코드가 이제 결과와 null을 비교할 책임이 있거나 NullReferenceException을 throw합니다. Framework Design Guidelines 2nd ed.을 인용

: 회원이 성공적으로 그것을 할 수 있도록 설계되었습니다 무엇 을 할 수없는 경우

, 그것은 실행 실패, 고려되어야하고 예외가 발생한다.

이름에서 알 수있는대로하지 않았습니다. 던지다!

키이스의 코드는 괜찮습니다. 예외를 로그하고 다시 시작하는 것이 좋습니다.

이것은 개인적인 방법이므로, 틀림없이 디자인 지침이 적용되지 않습니다. 그래도 예외 처리를 대신 사용할 수있는 경우 "if (result == null)"로 코드를 왜 버려야합니까?

+0

개체를 만들려고 시도하는 메서드를 사용하는 것이 유용한 경우도 있지만 그렇지 않을 경우 null을 반환합니다. 그러나 메서드에 그것이 할 일을 나타내는 이름을 부여하는 것은 좋은 생각입니다. Microsoft는 이러한 루틴을 성공/실패에 대한 부울 값을 반환하고 새 개체를 저장할 개체 참조 변수를 byref 매개 변수로 가지고 있지만 문에서 새 변수를 정의 할 수 있으므로 값 또는 null을 반환하는 것을 선호합니다. 인스턴스를 작성하려고합니다. – supercat

+0

@supercat : 반환 값이 null인지 항상 확인하기 위해 다른 개발자 (와 우리 자신)를 신뢰할 수 있다면 괜찮을 것입니다 ... – TrueWill

+0

TryGetFoo라는 함수를 호출하지 않으면 실패 할 수도 있습니다. MS 패턴 "TryGetFoo"메소드에서 리턴 값 (성공/실패 플래그)을 더 쉽게 무시할 수 있습니다. MS 패턴 버전은 좋은 상황이거나 나쁜 상황 일 수있는 기능을 가지고 있습니다. 함수가 예외를 throw하지만 전달되기 전에 변수를 무언가로 설정하는 것이 가능합니다. 변수가 IDisposable이면 좋지만 create 메소드의 리턴 코드가 무시되면 혼동을 줄 수 있습니다. – supercat