По сути, код, который перехватывает исключение, должен знать несколько вещей:
- Что случилось?
- Требует ли условие каких-либо конкретных действий?
- После выполнения вышеуказанного действия, если оно есть, исключительное условие считается выполненным.
- В каком состоянии будут находиться применимые объекты?
К сожалению, многие языки и фреймворки, включая C ++, Java и .net, пытаются использовать один довольно неуклюжий вид информации (тип брошенного объекта исключения) для передачи всех трех фрагментов информации, хотя на практике они ' часто во многом ортогональны. Особенно примечательная трудность такой конструкции состоит в том, что возможно одновременное возникновение нескольких исключительных условий, так что обработчики, применимые к ЛЮБОМУ из них, должны выполняться, но исключение должно продолжаться вверх по стеку, пока не будут запущены обработчики, применимые ко ВСЕМ из них.
Несмотря на ограничения типового дизайна, с ним приходится работать. При разработке собственных новых классов / интерфейсов и исключений, которые вытекают из них, следует попытаться использовать разные типы исключений для ответа на вопрос № 3- № 4 выше, поскольку эти вопросы, скорее всего, будут интересны вызывающему абоненту. Кроме того, я бы предположил, что для классов может быть желательно иметь переменную состояния или флаг, который может быть признан недействительным, если исключение, выброшенное из метода, может оставить класс в недопустимом состоянии, возможно, с использованием шаблона, например:
... before doing anything that might cause object to enter invalid state even temporarily ...
if (state != MyClassState.HappyIdle) throw new StateCorruptException(....);
state = MyClassState.UnhappyOrBusy;
... manipulate state in a fashion that will end up with a valid state when complete ...
state = MyClassState.HappyIdle;
Если такой шаблон используется последовательно, вызывающим абонентам не нужно будет слишком беспокоиться о возможности того, что операция, которая вызвала исключение, могла оставить объект в поврежденном состоянии, так что попытка продолжения операции может привести к дальнейшей потере данных , Если объект был поврежден, но вызывающий код игнорировал исключение, которое произошло, когда это произошло, дальнейшие попытки использовать объект будут безуспешными.
К сожалению, многие классы не очень хорошо защищены с помощью таких охранников, поэтому может быть небезопасно предполагать, что неизвестные исключения являются "безвредными". С другой стороны, с практической точки зрения не существует надежного и безопасного подхода. Либо рискуйте лишиться своего кода из-за ненужного исключения, которое на самом деле было бы безвредным, либо рискуйте испортить поврежденные структуры данных и повредить другие структуры данных. В лучше спроектированной системе исключений были бы лучшие альтернативы, но не с существующей системой.