Вопрос, который люди не упомянули, заключается в том, что, хотя языки .NET на самом деле не проводят должного различия, вопрос о том, должен ли предпринимать действия , когда происходит исключение, и будет ли он решить это, на самом деле, разные вопросы. Есть много случаев, когда нужно предпринимать действия, основанные на исключениях, которые не имеют надежды на разрешение, и есть случаи, когда все, что необходимо для «разрешения» исключения, - это размотать стек до определенной точки - никаких дальнейших действий не требуется. .
Из-за распространенного мнения, что нужно «ловить» только то, с чем можно «справиться», большой код, который должен действовать при возникновении исключений, этого не делает. Например, большая часть кода получает блокировку, «временно» помещает охраняемый объект в состояние, которое нарушает его инварианты, затем переводит его в законное состояние и затем снимает блокировку, прежде чем кто-либо еще сможет увидеть объект. Если возникает исключение, когда объект находится в опасно недопустимом состоянии, обычной практикой является снятие блокировки с объектом, все еще находящимся в этом состоянии. Гораздо лучше было бы иметь исключение, которое возникает, когда объект находится в «опасном» состоянии, и недействительно блокирует блокировку, поэтому любая будущая попытка получить ее немедленно потерпит неудачу. Последовательное использование такого шаблона значительно повысило бы безопасность обработки так называемых «покемонов», которая, по мнению IMHO, имеет плохую репутацию в первую очередь из-за кода, который позволяет исключениям возникать, не предпринимая соответствующих действий.
В большинстве языков .NET единственный способ для кода выполнить действие, основанное на исключении, - это catch
(хотя он и знает, что исключение не будет устранено), выполнить соответствующее действие и затем повторно выполнить throw
). Другой возможный подход, если код не заботится о том, какое исключение выдается, состоит в использовании флага ok
с блоком try/finally
; установите флаг ok
на false
перед блоком и на true
до выхода из блока и перед любым return
, который находится внутри блока. Затем, в пределах finally
, предположим, что, если ok
не установлено, должно произойти исключение. Такой подход семантически лучше, чем catch
/ throw
, но уродлив и менее ремонтопригоден, чем должен быть.