Использовать 'попробовать-наконец-то', не 'поймать' блок


есть ли ситуации, когда целесообразно использовать try-finally блок без catch блок?

11 52

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.

http://forums.asp.net/t/1092267.aspx?Try+without+Catch+but+with+finally+doesn+t+throw+error+Why+no+syntax+error+

вам нужен блок 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.

вот пример использования, который я всегда (uhm..) использование:

int? x; //note the nullable type here!
try
{
    x = int.Parse(someString);
}
catch { } //don't care, let it just be null

1.мы можем использовать блок try без catch, но мы должны использовать catch / finally, любой из них. 2.Мы не можем использовать только try block.