何时使用InvalidOperationException或NotSupportedException?

53

我正在实现一个自定义集合类实现,它可以是只读或非只读的;也就是说,所有改变集合内容的方法都会调用一个与下面函数在道德上相同的函数:

private void ThrowIfReadOnly() {
    if (this.isReadOnly)
       throw new SomeException("Cannot modify a readonly collection.");
}

我不确定在这种情况下应该使用NotSupportedException还是InvalidOperationException

1个回答

71
  • 对于这个特定话题,MSDN 只提供了一个指导,位于 NotSupportedException 页面上:
  • 如果有时对象可以执行请求的操作,并且对象状态决定是否可以执行操作,请参见InvalidOperationException

    接下来是我自己对规则的解释:

    • 如果对象的状态可以随着其生命周期而改变,以至于操作在对象的生命周期内可能变得无效/有效,则应使用 InvalidOperationException
    • 如果操作在整个对象生命周期内始终无效/有效,则应使用 NotSupportedException
    • 在这种情况下,“生命周期”意味着“任何人都可以获得对象引用的整个时间” - 也就是说,在调用 Dispose() 后,即使大多数其他实例方法不可用,对象仍然存在;
      • 正如 Martin Liversage 指出的那样,在对象已被处理的情况下,应使用更具体的 ObjectDisposedException 类型。(它仍然是 InvalidOperationException 的子类型)。

    在这种情况下,这些规则的实际应用如下:

    • 如果 isReadOnly 只能在对象创建时(例如构造函数参数)设置,而在任何其他时间都不能设置,则应使用 NotSupportedException
    • 如果 isReadOnly 可以在对象生命周期内更改,则应使用 InvalidOperationException
  • 然而,在实现集合时,InvalidOperationExceptionNotSupportedException 的区别实际上是无关紧要的 - 根据MSDN上IsReadOnly的描述,IsReadOnly唯一允许的行为是在集合初始化后其值永远不会更改。这意味着一个集合实例可以是可修改的或只读的 - 但它应该在初始化时选择其中之一,并在其余生命周期内坚持选择。

  • 6
    即使它是无效操作,对已释放的对象调用方法应该抛出“ObjectDisposedException”而不是“InvalidOperationException”。 - Martin Liversage
    4
    @Martin: 哦,很棒!我之前完全不知道 ObjectDisposedException。(而且由于 ObjectDisposedExceptionInvalidOperationException 的一个子类型,它与成为 InvalidOperationException 的特定情况相契合) - Jean Hominal

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接