Должен ли try / catch быть внутри или снаружи блока использования?

на using block-сокращение от try/catch/finally Я верю. В моем коде я ставил try/catch блок внутри the using блок, так что я могу поймать и регистрировать исключения с помощью моего собственного регистратора.

мне недавно было интересно, если try должно быть снаружи, таким образом, инкапсулируя using блок, или нет.

на мой взгляд, я уже боялся, что если исключение, то using блок не будет Dispose() of мой ресурс, потому что он выпрыгнул из блока и в обработчик catch. Но я могу ошибаться.

может кто-нибудь уточнить, какой правильный способ использовать оба using и try/catch вместе?

public HttpResponseMessage GetData(string x, int y)
{
    using (var client = new HttpClient())
    {
        try
        {
            // do stuff

            return response.Result;
        }
        catch (Exception ex)
        {
            // Something has gone badly wrong so we'll need to throw

            // Log the info

            throw;
        }
    }
}

5 ответов


using блок используется для обеспечения удаления (изменен с неоднозначного термина "немедленное удаление" на удаление, как предложено Джеймс) объектов, объявленных в using оператор, как только код выходит из using блок. Это не совсем сокращение для try/catch/finally. (Обратите внимание, что компилятор интерпретирует его как try-finally однако)

в вашем примере

using (var client = new HttpClient())
{
} //client will be disposed at any time after this line

зависит от случая, вы может рассмотреть поставить try-catch блок внутри или за пределами using блок.

например, если вам не нужно использовать элемент using объявление несколько раз (edit :что я имею в виду, если вам нужен элемент и на try и catch block-спасибо за ввод Мистер Коди Серый) - то есть, вам это нужно только в try, Я бы предложил использовать using блок внутри try заблокировать.

переведена на ваш случай, это зависит от того,var client предназначен для использования как для try и catch блоки. Если это так, то using должно быть вне try-catch блок. Иначе он должен быть внутри try заблокировать.

в общем, как правило, если элемент используется как в try и catch блок, а затем объявить using только один раз за пределами try-catch


это действительно зависит от того, какой ресурс вы беспокоитесь о том, чтобы быть утилизированным - если вы имеете в виду client вы должны быть хорошо. Я объясню, почему...

на мой взгляд, я ранее волновался, что если будет выброшено исключение, то блок using не будет Dispose() моего ресурса, потому что он выскочил из блока и в обработчик catch. Но я могу ошибаться.

Это не так, компилятор, вероятно, переписать код (возможно, более эффективно), например:

try
{
    try
    {
        // do stuff
        return response.Result;
    }
    catch (Exception ex)
    {
        // Something has gone badly wrong so we'll need to throw
        // Log the info
        throw;
    }
}
finally
{
    if (client != null)
        client.Dispose();
}

под нормальный обстоятельства a finally блок всегда будет выполняться, что означает, даже если вы ловите/повторной генерации исключения внутри using ваш Dispose вызов будет запущен.

таким образом, с технической точки зрения, внутри и снаружи не имеет значения.


на нем нет" правильного пути", только рекомендации. Однако я сам пытаюсь локализовать каждое исключение или любой код, насколько это возможно, то есть вы должны исключение, где оно может быть брошено, но где-то снаружи, по крайней мере, пока вам не нужно позволять вашему исключению пузыриться через разные слои.


в любом случае будет работать. Использование блоков гарантированно всегда вызывает Dispose() метод при выходе-это верно даже для стека un-ravelling для исключений, пойманных дальше по стеку.

посмотреть оператор using (ссылка на C#)

оператор using гарантирует, что метод Dispose вызывается даже если исключение возникает при вызове методов объекта. Вы можете достичь того же результата путем помещения объекта внутри блока try и затем вызов Dispose в блоке finally; фактически, именно так оператор using переводится компилятором. Пример кода ранее расширяется до следующего кода во время компиляции (обратите внимание на дополнительные фигурные скобки для создания ограниченной области для объекта):


лично я бы поставил try / catch / finally внутри using заблокировать.
Причина этого просто в том, что блок не будет бросать исключение, по крайней мере, не из моего опыта. Поэтому для простоты я буду иметь дело с исключениями, когда они происходят.