IT박스

.NET에서 유효하지 않거나 예기치 않은 매개 변수에 대해 어떤 예외가 발생합니까?

itboxs 2020. 6. 7. 10:51
반응형

.NET에서 유효하지 않거나 예기치 않은 매개 변수에 대해 어떤 예외가 발생합니까?


.NET에서 유효하지 않거나 예기치 않은 매개 변수에 대해 어떤 유형의 예외를 발생시켜야합니까? 언제 다른 것을 선택하지 않습니까?

후속 조치 :

한 달에 해당하는 정수를 기대하는 함수가 있고 '42'를 전달한 경우 어떤 예외를 사용합니까? 컬렉션이 아니더라도 "범위를 벗어난"범주에 속합니까?


: 내가 사용하려면 ArgumentException, ArgumentNullException하고 ArgumentOutOfRangeException.

인수 자체에 그다지 초점을 맞추지 않고 호출을 전체적으로 판단하는 다른 옵션도 있습니다.

  • InvalidOperationException– 인수가 정상일 수 있지만 오브젝트의 현재 상태가 아닙니다. 크레딧은 STW (이전 Yoooder)로갑니다. 그의 답변도 투표하십시오 .
  • NotSupportedException– 전달 된 인수는 유효하지만이 구현에서는 지원되지 않습니다. FTP 클라이언트를 상상하고 클라이언트가 지원하지 않는 명령을 전달합니다.

트릭은 왜 메소드를 원래대로 호출 할 수 없는지를 가장 잘 나타내는 예외를 처리하는 것입니다. 이상적으로 무엇이 잘못되었는지, 왜 잘못되었는지, 어떻게 고쳐야하는지에 대한 예외를 구체적으로 설명해야합니다.

오류 메시지가 도움, 문서 또는 기타 리소스를 가리키는 것을 좋아합니다. 예를 들어, Microsoft는 KB 기사 (예 : "Internet Explorer의 웹 페이지를 방문 할 때"작업이 중단되었습니다 "오류 메시지가 표시되는 이유는 무엇입니까?) 와 함께 첫 단계를 밟았습니다." . 오류가 발생하면 오류 메시지의 KB 기사를 가리 킵니다. 그들이 잘하지 못하는 것은 그들이 왜 실패했는지 말해주지 않는다는 것입니다.

의견을 다시 한 번 STW (ex Yoooder)에게 감사드립니다.


후속 조치에 따라을 (를) 던질 것 ArgumentOutOfRangeException입니다. 이 예외에 대한 MSDN의 의견을 살펴보십시오.

ArgumentOutOfRangeException메서드가 호출되고 메서드에 전달 된 인수 중 하나 이상이 Null 참조가 아니고 ( NothingVisual Basic의 경우) 유효한 값을 포함하지 않으면 throw됩니다 .

따라서이 경우 값을 전달하지만 범위가 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.

요우 더의 대답이 저를 깨달았습니다. 입력은 유효하지 않은 입력이있는 동안은 언제든지 유효하지 않은 경우 예상치 못한 이 시스템의 현재 상태에 대해 유효하지 않은 경우. 따라서 나중에 InvalidOperationException는 합리적인 선택입니다.


인수 예외.

  • System.ArgumentException
  • System.ArgumentNullException
  • System.ArgumentOutOfRangeException

ArgumentException :

ArgumentException은 메소드가 호출되고 전달 된 인수 중 하나 이상이 호출 된 메소드의 매개 변수 스펙을 충족하지 않는 경우 발생합니다. ArgumentException의 모든 인스턴스에는 유효하지 않은 인수와 인수의 예상 값 범위를 설명하는 의미있는 오류 메시지가 포함되어야합니다.

A few subclasses also exist for specific types of invalidity. The link has summaries of the subtypes and when they should apply.


Short answer:
Neither

Longer answer:
using Argument*Exception (except in a library that is a product on its on, such as component library) is a smell. Exceptions are to handle exceptional situation, not bugs, and not user's (i.e. API consumer) shortfalls.

Longest answer:
Throwing exceptions for invalid arguments is rude, unless you write a library.
I prefer using assertions, for two (or more) reasons:

  • Assertions don't need to be tested, while throw assertions do, and test against ArgumentNullException looks ridiculous (try it).
  • Assertions better communicate the intended use of the unit, and is closer to being executable documentation than a class behavior specification.
  • You can change behavior of assertion violation. For example in debug compilation a message box is fine, so that your QA will hit you with it right away (you also get your IDE breaking on the line where it happens), while in unit test you can indicate assertion failure as a test failure.

Here is what handling of null exception looks like (being sarcastic, obviously):

try {
    library.Method(null);
}
catch (ArgumentNullException e) {
    // retry with real argument this time
    library.Method(realArgument);
}

Exceptions shall be used when situation is expected but exceptional (things happen that are outside of consumer's control, such as IO failure). Argument*Exception is an indication of a bug and shall be (my opinion) handled with tests and assisted with Debug.Assert

BTW: In this particular case, you could have used Month type, instead of int. C# falls short when it comes to type safety (Aspect# rulez!) but sometimes you can prevent (or catch at compile time) those bugs all together.

And yes, MicroSoft is wrong about that.


There is a standard ArgumentException that you could use, or you could subclass and make your own. There are several specific ArgumentException classes:

http://msdn.microsoft.com/en-us/library/system.argumentexception(VS.71).aspx

Whichever one works best.

참고URL : https://stackoverflow.com/questions/774104/what-exceptions-should-be-thrown-for-invalid-or-unexpected-parameters-in-net

반응형