Использовать 'попробовать-наконец-то', не 'поймать' блок
есть ли ситуации, когда целесообразно использовать try-finally блок без catch блок?
11 ответов:
вы бы использовали его, чтобы обеспечить некоторые действия происходят после
tryсодержимое или исключение, но когда вы не хотите использовать это исключение.просто чтобы быть ясным, это не скрывает исключений. Элемент
finallyблок перед исключение передается вверх по стеку вызовов.вы случайно использовать его, когда вы используете
usingключевое слово, потому что это компилируется вtry-finally(не точное преобразование, но для аргумента это близко достаточно.)try { TrySomeCodeThatMightException(); } finally { CleanupEvenOnFailure(); }код
finallyне гарантируется запуск, однако случай, когда он не гарантирован, довольно краевой - я даже не могу его вспомнить. Все, что я помню, если вы в этом случае, шансы очень хорошие, что не работаетfinallyэто не ваша самая большая проблема : -) так что в основном не потейте.обновление от Тобиаса:
finallyне будет работать, если процесс будет убит.обновление от Пэдди: условиях, когда окончательно не выполнить .чистый попробовать..наконец, блок
наиболее распространенный пример, который вы можете увидеть, - это удаление подключения к базе данных или внешнего ресурса, даже если код не работает:
using (var conn = new SqlConnection("")) // Ignore the fact we likely use ORM ;-) { // Do stuff. }компилируется в что-то как:
SqlConnection conn; try { conn = new SqlConnection(""); // Do stuff. } finally { if (conn != null) conn.Dispose(); }
usingэквивалентноtry-finally. Вы будете использовать толькоtry-finallyкогда вы хотите сделать некоторые очистке внутриfinallyи не волнует исключение.The лучший подход будет
try { using(resource) { //Do something here } }catch(Exception) { //Handle Error }это даже очистить называется
usingfails, ваш код не будет терпеть неудачу.есть некоторые условия, когда
finallyне будет выполняться.
- если таковые имеются
StackOverflowExceptionилиExecutingEngineException.
если у вас есть, например, неуправляемый ресурс, который вы создаете и используете в блоке try, вы можете использовать блок finally, чтобы освободить этот ресурс. Блок finally всегда будет выполняться, несмотря на то, что происходит (например, исключения) в блоке try.
например, оператор lock(x) действительно:
System.Threading.Monitor.Enter(x); try { ... } finally { System.Threading.Monitor.Exit(x); }блок finally всегда будет вызываться, чтобы гарантировать, что исключительная блокировка будет освобождена.
хорошее объяснение с помощью кода:
void MyMethod1() { try { MyMethod2(); MyMethod3(); } catch(Exception e) { //do something with the exception } } void MyMethod2() { try { //perform actions that need cleaning up } finally { //clean up } } void MyMethod3() { //do something }если MyMethod2 или MyMethod3 создает исключение, оно будет поймано MyMethod1. Однако код в MyMethod2 должен выполнить очистку кода, например, закрытие соединения с базой данных, прежде чем исключение будет передано в MyMethod1.
вам нужен блок finally, когда независимо от того, какие (если есть) исключения пойманы или даже если они не пойманы, вы все равно хотите выполнить некоторый код до выхода блока. Например, вы можете закрыть открытый файл.
См. Также попробовать-наконец-то
try / finally: когда вы не хотите обрабатывать какие-либо исключения, но хотите убедиться, что некоторые действия происходят независимо от того, вызвано ли исключение вызываемым кодом.
посмотрите на следующую ссылку: https://softwareengineering.stackexchange.com/questions/131397/why-use-try-finally-without-a-catch-clause
Это зависит от архитектуры вашего приложения и работу в блоке.
вот ситуация, когда вы можете использовать try finally: когда вы обычно используете оператор using, но не можете, потому что вы вызываете метод путем отражения.
это не сработает
using (objMsg = Activator.CreateInstance(TypeAssist.GetTypeFromTypeName("omApp.MessagingBO"))) { }вместо того, чтобы использовать
object objMsg = null; try { objMsg = Activator.CreateInstance(TypeAssist.GetTypeFromTypeName("myAssembly.objBO")); strResponse = (string)objMsg.GetType().InvokeMember("MyMethod", BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod, null, objMsg, new object[] { vxmlRequest.OuterXml }); } finally { if (objMsg!=null) ((IDisposable)objMsg).Dispose(); }
Я ничего не знаю о C#, но кажется, что все, что вы могли бы сделать с попыткой-наконец, вы могли бы более элегантно сделать с используя заявлением. C++ даже не имеет finally as результат его RAII.