C# 对于.NET中无效或意外的参数,应引发哪些异常?

C# 对于.NET中无效或意外的参数,应引发哪些异常?,c#,.net,vb.net,exception,C#,.net,Vb.net,Exception,对于.NET中无效或意外的参数,应引发哪些类型的异常?我什么时候会选择一个而不是另一个 后续行动: 如果您有一个函数需要一个与月份对应的整数,并且您传入了'42',您会使用哪个异常?即使这不是一个系列,它是否也属于“超出范围”类别 System.ArgumentException System.ArgumentNullException System.ArgumentOutOfRangeException 根据实际值和最适合的例外情况: (数值有问题) (参数为null,但不允许使用此参数

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

后续行动: 如果您有一个函数需要一个与月份对应的整数,并且您传入了'42',您会使用哪个异常?即使这不是一个系列,它是否也属于“超出范围”类别

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

根据实际值和最适合的例外情况:

  • (数值有问题)

  • (参数为null,但不允许使用此参数)

  • (参数的值超出有效范围)

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


尤德的回答启发了我。如果输入在任何时候都无效,则该输入无效;如果输入在系统当前状态下无效,则该输入为意外输入。因此,在后一种情况下,an是一个合理的选择。

我喜欢使用:
ArgumentException
ArgumentNullException
ArgumentOutOfRangeException

  • –论点有点不对劲
  • –参数为空
  • –我不经常使用这个,但一个常见的用法是索引到集合中,并给出一个非常大的索引
还有其他选择,它们不太关注争论本身,而是从整体上判断这一呼吁:

  • –参数可能正常,但不在对象的当前状态。归功于STW(之前的Yoooder)。也投票赞成
  • –传入的参数有效,但在此实现中不受支持。想象一个FTP客户端,您传递了一个客户端不支持的命令
诀窍是抛出一个异常,该异常最好地表达了为什么无法按原样调用该方法。理想情况下,异常应该详细说明出错的原因、原因以及如何修复

我喜欢错误消息指向帮助、文档或其他资源。例如,微软在知识库文章上迈出了良好的第一步,例如。当您遇到错误时,它们会将您指向错误消息中的知识库文章。他们做得不好的是他们没有告诉你为什么失败

再次感谢STW(前Yoooder)的评论


作为对你后续行动的回应,我将抛出一个。请看MSDN对此异常的说明:

将抛出ArgumentOutOfRangeException 调用方法时,至少 传递给 方法不为null 参考(
Nothing
在Visual Basic中) 和不包含有效值

因此,在本例中,您传递的是一个值,但这不是一个有效值,因为您的范围是1–12。然而,您记录它的方式很清楚,您的API抛出了什么。因为尽管我可能会说
ArgumentOutOfRangeException
,但另一个开发人员可能会说
ArgumentException
。简化操作并记录行为。

ArgumentException在 方法被调用,并且至少有一个 传递的参数不符合 被调用函数的参数说明 方法。所有实例 异常应带有 有意义的错误消息描述 无效参数以及 所需的值范围 争论


对于特定类型的残疾,也存在一些子类。该链接包含子类型的摘要以及它们应该应用的时间。

有一个标准的ArgumentException,您可以使用,或者您可以对其进行子类化并创建自己的子类。有几个特定的ArgumentException类:

无论哪一个效果最好。

我投了赞成票,但想在列表中再添加一个:

如果参数有效,但对象处于不应使用参数的状态,则应引发System.InvalidOperationException

更新取自MSDN:

在中使用InvalidOperationException 当未能调用 方法是由其他原因引起的 无效参数

假设您的对象有一个PerformAction(enmSomeAction)方法,有效的enmSomeActions是打开和关闭的。如果连续调用PerformAction(enmSomeAction.Open)两次,则第二次调用应引发InvalidOperationException(因为Arumgin是有效的,但不适用于控件的当前状态)

由于您已经通过防御性编程做了正确的事情,我还要提到另一个例外是ObjectDisposedException如果您的对象实现了IDisposable,那么您应该始终有一个类变量跟踪已处置的状态;如果您的对象已被释放,并且对其调用了一个方法,则应引发ObjectDisposedException:

public void SomeMethod()
{
    If (m_Disposed) {
          throw new ObjectDisposedException("Object has been disposed")
     }
    // ... Normal execution code
}
更新:回答您的后续问题:这有点模棱两可,并且由于使用泛型(而不是.NET泛型意义上的)数据类型来表示特定的数据集而变得更为复杂;枚举或其他强类型对象将是更理想的选择——但我们并不总是拥有这种控制

我个人倾向于ArgumentOutOfRangeException,并提供一条消息,指示有效值为1-12。我的推理是,当你谈论月份时,假设月份的所有整数表示都是有效的,那么你期望的值是1-12。如果只有某些月份(比如有31天的月份)是有效的,那么你就不会处理范围本身,我会抛出一个指示有效值的通用ArgumentException,我会
try {
    library.Method(null);
}
catch (ArgumentNullException e) {
    // retry with real argument this time
    library.Method(realArgument);
}