.NET中的无效或意外参数应该抛出哪些异常?

Eve*_*ien 157 .net c# vb.net exception

对于.NET中的无效或意外参数,应该抛出哪些类型的异常?我什么时候选择一个而不是另一个?

跟进:

如果你的函数需要一个对应于一个月的整数并且你传入'42',那么你会使用哪个例外?即使它不是一个集合,它会属于"超出范围"类别吗?

Jos*_*rke 241

我喜欢用:ArgumentException,ArgumentNullException,和ArgumentOutOfRangeException.

还有其他选择,它们不太关注论证本身,而是将整个呼叫判断:

  • InvalidOperationException - 参数可能没问题,但不在对象的当前状态.归功于STW(以前的Yoooder).也可以投票给他答案.
  • NotSupportedException - 传入的参数有效,但在此实现中不受支持.想象一下FTP客户端,并传递客户端不支持的命令.

诀窍是抛出最能表达为什么不能按原样调用方法的异常.理想情况下,应该详细说明出错的原因,错误原因以及解决方法.

我喜欢错误消息指向帮助,文档或其他资源.例如,微软在他们的知识库文章中做了很好的第一步,例如"当我在Internet Explorer中访问网页时,为什么会收到"操作已中止"错误消息?".当您遇到错误时,他们会将您指向错误消息中的知识库文章.他们做得不好的是,他们没有告诉你,为什么特别失败.

感谢STW(前Yoooder)的评论.


为了回应你的后续行动,我会抛出一个ArgumentOutOfRangeException.看看MSDN对这个例外的看法:

ArgumentOutOfRangeException调用方法并且传递给方法的至少一个参数不是空引用(Nothing在Visual Basic中)并且不包含有效值时抛出.

因此,在这种情况下,您传递的是值,但这不是有效值,因为您的范围是1-12.但是,您记录它的方式清楚地说明了您的API抛出的内容.因为虽然我可能会说ArgumentOutOfRangeException,另一位开发者可能会说ArgumentException.轻松记录行为.

  • 注意,如果你捕获ArgumentException,它也会捕获ArgumentOutOfRange. (4认同)

STW*_*STW 43

我投票支持Josh的答案,但是想在列表中添加一个:

System.InvalidOperationException should be thrown if the argument is valid, but the object is in a state where the argument shouldn't be used.

Update Taken from MSDN:

InvalidOperationException is used in cases when the failure to invoke a method is caused by reasons other than invalid arguments.

Let's say that your object has a PerformAction(enmSomeAction action) method, valid enmSomeActions are Open and Close. If you call PerformAction(enmSomeAction.Open) twice in a row then the second call should throw the InvalidOperationException (since the arugment was valid, but not for the current state of the control)

Since you're already doing the right thing by programming defensively I have one other exception to mention is ObjectDisposedException. If your object implements IDisposable then you should always have a class variable tracking the disposed state; if your object has been disposed and a method gets called on it you should raise the ObjectDisposedException:

public void SomeMethod()
{
    If (m_Disposed) {
          throw new ObjectDisposedException("Object has been disposed")
     }
    // ... Normal execution code
}
Run Code Online (Sandbox Code Playgroud)

Update: To answer your follow-up: It is a bit of an ambiguous situation, and is made a little more complicated by a generic (not in the .NET Generics sense) data type being used to represent a specific set of data; an enum or other strongly typed object would be a more ideal fit--but we don't always have that control.

I would personally lean towards the ArgumentOutOfRangeException and provide a message that indicates the valid values are 1-12. My reasoning is that when you talk about months, assuming all integer representations of months are valid, then you are expecting a value in the range of 1-12. If only certain months (like months that had 31 days) were valid then you would not be dealing with a Range per-se and I would throw a generic ArgumentException that indicated the valid values, and I would also document them in the method's comments.


Dan*_*ner 35

取决于实际值和最适合的异常:

如果这不够精确,只需从中派生自己的异常类ArgumentException.

Yoooder的答案启发了我.如果输入在任何时间无效,则输入无效,而如果输入对系统的当前状态无效,则输入是意外的.所以在后一种情况下,a InvalidOperationException是一个合理的选择.

  • 摘自MSDN关于InvalidOperationException的页面:"如果调用方法失败是由无效参数以外的原因引起的,则使用InvalidOperationException." (6认同)

Sye*_*Ali 6

参数异常。

  • 系统参数异常
  • 系统参数NullException
  • System.ArgumentOutOfRangeException