.NET에서 유효하지 않거나 예기치 않은 매개 변수에 대해 어떤 유형의 예외를 발생시켜야합니까? 언제 다른 것을 선택하지 않습니까?
후속 조치 :
한 달에 해당하는 정수를 기대하는 함수가 있고 ’42’를 전달한 경우 어떤 예외를 사용합니까? 컬렉션이 아니더라도 “범위를 벗어난”범주에 속합니까?
답변
: 내가 사용하려면 ArgumentException
, ArgumentNullException
하고 ArgumentOutOfRangeException
.
ArgumentException
– 논쟁에 문제가 있습니다.ArgumentNullException
– 인수가 널입니다.ArgumentOutOfRangeException
– 나는 이것을 많이 사용하지 않지만, 일반적인 용도는 컬렉션으로 색인을 생성하고 큰 색인을주는 것입니다.
인수 자체에 그다지 초점을 맞추지 않고 전화를 전체적으로 판단하는 다른 옵션도 있습니다.
InvalidOperationException
– 인수가 정상일 수 있지만 오브젝트의 현재 상태가 아닙니다. 크레딧은 STW (이전 Yoooder)로갑니다. 그의 답변도 투표하십시오 .NotSupportedException
– 전달 된 인수는 유효하지만이 구현에서는 지원되지 않습니다. FTP 클라이언트를 상상하고 클라이언트가 지원하지 않는 명령을 전달합니다.
트릭은 왜 메소드를 원래대로 호출 할 수 없는지를 가장 잘 나타내는 예외를 처리하는 것입니다. 이상적으로 무엇이 잘못되었는지, 왜 잘못되었는지, 어떻게 고쳐야하는지에 대한 예외를 구체적으로 설명해야합니다.
오류 메시지가 도움, 문서 또는 기타 리소스를 가리키는 것을 좋아합니다. 예를 들어, Microsoft는 KB 기사 (예 : “Internet Explorer의 웹 페이지를 방문 할 때”작업이 중단되었습니다 “오류 메시지가 표시되는 이유는 무엇입니까?) 와 함께 첫 단계를 밟았습니다.” . 오류가 발생하면 오류 메시지의 KB 기사를 가리 킵니다. 그들이 잘하지 못하는 것은 그들이 왜 실패했는지 말해주지 않는다는 것입니다.
의견을 다시 한 번 STW (ex Yoooder)에게 감사드립니다.
후속 조치에 따라 ArgumentOutOfRangeException
입니다. 이 예외에 대한 MSDN의 의견을 살펴보십시오.
ArgumentOutOfRangeException
메소드가 호출되고 메소드에 전달 된 인수 중 하나 이상이 널 참조가 아닌 경우 발생합니다 (Nothing
Visual Basic의 경우) 유효한 값을 포함하지 않을 때 발생합니다.
따라서이 경우 값을 전달하지만 범위가 1-12이므로 유효한 값이 아닙니다. 그러나 문서화 방식에 따라 API에서 발생하는 사항이 명확 해집니다. 내가 말할 수도 있지만 ArgumentOutOfRangeException
다른 개발자가 말할 수도 있습니다 ArgumentException
. 쉽게 행동을 문서화하십시오.
답변
Josh의 답변에 투표했습니다 했지만 목록에 하나 더 추가하고 싶습니다.
인수가 유효하지만 개체가 인수를 사용하지 않아야하는 상태 인 경우 System.InvalidOperationException이 발생해야합니다.
MSDN에서 가져온 업데이트 :
InvalidOperationException은 유효하지 않은 인수 이외의 이유로 메소드 호출 실패가 발생한 경우에 사용됩니다.
객체에 PerformAction (enmSomeAction action) 메소드가 있고 유효한 enmSomeActions가 Open 및 Close라고 가정합니다. PerformAction (enmSomeAction.Open)을 연속으로 두 번 호출하면 두 번째 호출에서 InvalidOperationException이 발생합니다 (약자가 유효하지만 제어의 현재 상태가 아니기 때문에).
방어 적으로 프로그래밍하여 이미 옳은 일을하고 있기 때문에 언급 할 또 다른 예외는 ObjectDisposedException입니다. 객체가 IDisposable을 구현하는 경우 항상 폐기 된 상태를 추적하는 클래스 변수가 있어야합니다. 객체가 삭제되고 메소드가 호출되면 ObjectDisposedException을 발생시켜야합니다.
public void SomeMethod()
{
If (m_Disposed) {
throw new ObjectDisposedException("Object has been disposed")
}
// ... Normal execution code
}
최신 정보: 후속 조치에 대답하기 : 약간 모호한 상황이며 특정 데이터 세트를 나타내는 데 사용되는 일반 (.NET Generics 의미가 아닌) 데이터 유형에 의해 조금 더 복잡해집니다. 열거 형 또는 다른 강력한 형식의 개체가 더 이상적으로 적합 할 수 있지만 항상 해당 제어 기능이있는 것은 아닙니다.
개인적으로 ArgumentOutOfRangeException에 기대어 유효한 값이 1-12임을 나타내는 메시지를 제공합니다. 내 추론은 개월에 대한 모든 정수 표현이 유효하다고 가정하고 개월에 대해 이야기 할 때 1-12 범위의 값을 기대한다는 것입니다. 특정 달 (31 일이있는 달과 같은) 만 유효하다면 Range per-se를 다루지 않을 것이고 유효한 값을 나타내는 일반적인 ArgumentException을 throw하고 메소드의 주석에 문서화 할 것입니다.
답변
실제 값과 어떤 예외가 가장 적합한 지에 따라
-
ArgumentException
(값에 문제가 있습니다) -
ArgumentNullException
(이는 허용되지 않지만 인수는 null입니다) -
ArgumentOutOfRangeException
(인수가 유효 범위를 벗어난 값을 가짐)
이것이 정확하지 않은 경우에서 자신의 예외 클래스를 파생하십시오 ArgumentException
.
요우 더의 대답이 저를 깨달았습니다. 입력은 유효하지 않은 입력이있는 동안은 언제든지 유효하지 않은 경우 예상치 못한 이 시스템의 현재 상태에 대해 유효하지 않은 경우. 따라서 나중에 InvalidOperationException
는 합리적인 선택입니다.
답변
- System.ArgumentException
- System.ArgumentNullException
- System.ArgumentOutOfRangeException
답변
ArgumentException은 메소드가 호출되고 전달 된 인수 중 하나 이상이 호출 된 메소드의 매개 변수 스펙을 충족하지 않는 경우 발생합니다. ArgumentException의 모든 인스턴스에는 유효하지 않은 인수와 인수의 예상 값 범위를 설명하는 의미있는 오류 메시지가 포함되어야합니다.
특정 유형의 무효성에 대해 몇 개의 서브 클래스도 존재합니다. 링크에는 하위 유형과 적용시기가 요약되어 있습니다.
답변
짧은 대답 :
둘 다
더 긴 대답 :
Argument * 예외 사용 (구성 요소 라이브러리와 같이 제품이있는 라이브러리 제외)은 냄새입니다. 예외는 버그가 아닌 예외적 인 상황을 처리하고 사용자 (즉, API 소비자) 부족이 아닌 경우를 처리하는 것입니다.
가장 긴 대답 :
라이브러리를 작성하지 않으면 유효하지 않은 인수에 대한 예외를 던지는 것은 무례합니다.
나는 두 가지 이상의 이유로 단언을 사용하는 것을 선호한다.
- 어설 션은 테스트 할 필요가 없으며 던지기 어설 션은 수행 할 수 있으며 ArgumentNullException에 대한 테스트는 어리석은 것처럼 보입니다 (시도하십시오).
- 어설 션은 장치의 의도 된 용도를보다 잘 전달하며 클래스 동작 사양보다 실행 가능한 문서에 더 가깝습니다.
- 어설 션 위반 동작을 변경할 수 있습니다. 예를 들어 디버그 컴파일에서 메시지 상자는 괜찮습니다. 따라서 QA가 메시지를 즉시 받아 낼 수 있습니다 (IDE가 발생하는 라인에서 끊어짐) 단위 테스트에서는 어설 션 실패를 테스트 실패로 나타낼 수 있습니다 .
null 예외 처리는 다음과 같습니다 (확실히 냉소적 임).
try {
library.Method(null);
}
catch (ArgumentNullException e) {
// retry with real argument this time
library.Method(realArgument);
}
상황이 예상되지만 예외적 인 경우 (예 : IO 실패와 같이 소비자가 통제 할 수없는 경우) 예외를 사용해야합니다. 인수 * 예외는 버그를 나타내며 테스트로 처리하고 디버그를 지원해야합니다.
BTW :이 경우 int 대신 Month 유형을 사용했을 수 있습니다. 타입 안전 (Aspect # rulez!)에 관해서는 C #이 부족하지만 때로는 이러한 버그를 모두 방지하거나 컴파일 할 수 있습니다.
그리고 네, MicroSoft는 그것에 대해 틀 렸습니다.
답변
사용할 수있는 표준 ArgumentException이 있거나 서브 클래스 화하여 직접 만들 수 있습니다. 몇 가지 특정 ArgumentException 클래스가 있습니다.
http://msdn.microsoft.com/en-us/library/system.argumentexception(VS.71).aspx
어느 것이 가장 효과가 좋은지.
