Подтвердить что ты не робот

Какое исключение выбрасывает недопустимое состояние объекта?

Я всегда пропускал встроенный тип исключения в С#, который указывал бы, что объект поврежден. Что вы бросаете в таких случаях?

Обычно я пропускаю это, когда понимаю, что метод, который должен работать на объекте, потерпит неудачу, если объект имеет определенное состояние. В таких ситуациях я часто подозреваю, что этого состояния, вероятно, никогда не достигнут. Но, защищаясь, я хотел бы сделать исключение на случай, если это произойдет (например, после изменения будущего кода).

Для аргументов метода мы имеем ArgumentException, чтобы мы могли отрицать недопустимые параметры. Но для состояния объекта? В Java я бы использовал IllegalStateException.

Конечно, вы можете утверждать, что методы, которые фактически меняют состояние, могут проверять правильность состояния. И они лучше должны, но тогда, если они этого не сделают (скажем, в унаследованных божественных классах)?

Edit:

Несмотря на то, что 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); 
}
4b9b3361

Ответ 1

Вам следует бросить InvalidOperationException, чтобы указать, что объект имеет недопустимое состояние.

В документации MSDN (см. выше):

Исключение, которое вызывается, когда вызов метода недействителен для текущего состояния объекта.

Ответ 2

Самый близкий аналог, который я могу представить как .Net 2.0 [что-то лучше, возможно, было добавлено с момента], будет ObjectDisposedException, что указывает на то, что объект был помещен в состояние с неизменным состоянием. Такое исключение можно считать "неожиданным", но это хорошо, поскольку условие, которое оно указывает, было бы также неожиданным. Кроме того, если метод объекта обнаруживает, что его состояние является недопустимым, он должен после сбора как можно большего количества информации о состоянии объекта, который может быть полезен для устранения неполадок, преднамеренно помещает объект в состояние с неизменным статусом, чтобы все будущие операции на него (кроме, возможно, запросов на извлечение информации, которая была записана для целей устранения неполадок) генерирует исключение.

Из-за сильной связи между IDisposable и ObjectDisposedException может быть лучше определить новый тип исключения, который может или не может наследоваться от ObjectDisposedException. Возможно, ObjectDisposedException должен был быть получен из ObjectInvalidatedException, который также должен иметь CorruptObjectDiscoveredException и CorruptObjectInvalidatedException [первый из них был брошен первым методом, который обнаруживает повреждение, а второй - последующими вызовами метода на том же объект], но я не уверен, что это действительно важно.

Самое главное, что я считаю, что код, который имеет основания полагать, что объект может находиться в коррумпированном состоянии, явно делает недействительным объект. Некоторые люди предположили, что методы, которые открывают неожиданные проблемы, должны пытаться уничтожить всю систему. Я категорически не согласен с этой философией. Если метод помещает объект в то, что должно быть временно поврежденным состоянием, а затем выходит через исключение, прежде чем состояние объекта может быть исправлено, оно должно полностью аннулировать объект, а не оставлять его поврежденным. Если после разворачивания стека система не может функционировать без объекта, который теперь недействителен, он будет рушиться в коротком порядке (лучший вариант, чем работа с поврежденным состоянием). Если, однако, процесс разворачивания стека приводит к отказу от коррумпированного объекта (например, кто-то пытался загрузить документ из файла неправильного типа, вызывая исключение в методе, называемом LoadDocument), тот факт, что теперь заброшенный объект был поврежден, может быть полезной информацией для понимания причины исключения, но не может нести противовключения общего состояния системы.