Использовать 'попробовать-наконец-то', не 'поймать' блок
есть ли ситуации, когда целесообразно использовать 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 }
это даже очистить называется
using
fails, ваш код не будет терпеть неудачу.есть некоторые условия, когда
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.