对无效对象状态引发的异常

本文关键字:异常 状态 无效 对象 | 更新日期: 2023-09-27 18:12:09

我总是错过 c# 中的内置异常类型,该类型指示对象已损坏。在这种情况下,你会扔什么?

通常,当我意识到一个应该在对象上工作的方法如果对象具有某种状态会失败时,我会错过它。在这种情况下,我经常怀疑这种状态可能永远不会达到。但是为了防御它,我想抛出一个异常以防万一(例如,在未来的代码更改之后(。

对于方法参数,我们ArgumentException,因此我们可以拒绝无效参数。但是对于对象状态?在Java中,我会使用IllegalStateException

当然,你可以争辩说,实际上改变状态的方法可以检查状态的正确性。他们最好应该这样做,但如果他们不这样做(比如在遗产神类中(?

编辑:

尽管InvalidOperationException似乎是最合适的,但正如公认的答案所述(也是这个(,请注意:

这是微妙的,但在语义上这与InvalidOperationException的含义不同。 InvalidOperationException表示对象的"协议"存在问题,调用方必须遵守(例如,未初始化,已经关闭,...在我的情况下,调用者没有做错任何事,是对象被破坏了。我想传达确切的信息。

例:

switch(this._someType) {
  case SomeType.A: doSomething(); break;
  case SomeType.B: doSomethingElse(); break;
  /*...*/
  default:
    // Unexpected type! Someone introduced a new type and didn't update this.
    throw new IllegalStateException("Unknown type "+this._someType); 
}

对无效对象状态引发的异常

你应该抛出InvalidOperationException来指示对象具有无效状态。

从 MSDN 文档(上面链接(:

当方法调用对对象的当前状态无效时引发的异常。

截至 .Net 2.0 我能想到的最接近的类比 [可能已经添加了更好的东西] 是 ObjectDisposedException ,这表明一个对象已被置于永久无效状态。 这样的异常可能被认为是"意外的",但这是一件好事,因为它所指示的条件同样是出乎意料的。 此外,如果对象上的方法发现其状态无效,则应在捕获有关对象状态的尽可能多的信息(可能有助于故障排除(之后,故意将对象置于永久无效状态,以便将来对其执行的所有操作(可能请求提取为故障排除目的而捕获的信息(将引发异常。

由于IDisposableObjectDisposedException之间的强关联,最好定义一个新的异常类型,该异常类型可能会也可能不会继承自ObjectDisposedException。 可以说,ObjectDisposedException应该派生自一个ObjectInvalidatedException,它也应该具有CorruptObjectDiscoveredExceptionCorruptObjectInvalidatedException[前者由发现损坏的第一个方法抛出,后者由后续方法调用同一对象],但我不确定这是否真的重要。

我认为最重要的是确保有理由相信对象可能处于损坏状态的代码明确使对象无效。 有些人建议发现意外问题的方法应该尝试破坏整个系统。 我强烈反对这种哲学。 如果一个方法将对象置于应该是暂时损坏的状态,然后在修复对象的状态之前通过异常退出,则它应该使对象完全无效,而不是使其损坏。 如果在堆栈展开后,系统在没有现在失效的对象的情况下无法运行,它将在短时间内崩溃(比在损坏状态下运行更好的选择(。 但是,如果展开堆栈的过程导致损坏的对象被放弃(例如,有人试图从错误类型的文件中加载文档,导致LoadDocument调用的方法中出现异常(,则现在放弃的对象已损坏的事实可能是理解为什么抛出异常的有用信息, 但不可能对系统的整体运行状况产生不利影响。