Инициализация одноразовых ресурсов снаружи или внутри try / finally

Я видел два способа приобретения и использования ресурсов. Либо:

Resource resource = getResource();
try { /* do something with resource */ }
finally { resource.close(); }

или же:

Resource resource = null;
try { resource = getResource(); /* do something with resource */ }
finally { if (resource != null) resource.close(); }

Мне было интересно, какой стиль предпочтительнее. Первый позволяет избежать условия if, а второй (я полагаю) обрабатывает случай прерывания потока сразу после назначения, но до входа в блок try. Какие еще плюсы и минусы есть у этих стилей друг перед другом? Какой из них я предпочитаю использовать?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
5
0
2 872
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Если getResource () вызывает исключение, тогда ресурс будет нулевым, getResource () ничего не возвращает в случае исключения. Итак, пока getResource () может генерировать исключение, всегда проверяйте значение null перед вызовом resource.close (). Я считаю, что лучший способ организовать этот код - поместить все в блок try; проясните, что getResource () генерирует исключения.

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

Jon Skeet 20.01.2009 23:59

В аналогичном коде, где, скажем, происходит захват и освобождение блокировки, сбой в получении приведет к несогласованному освобождению.

Tom Hawtin - tackline 21.01.2009 02:51
Ответ принят как подходящий

В C# просто используйте оператор using:

using (Resource resource = GetResource())
{
    /* Do something */
}

Это идиоматический способ очистки ресурсов, основанный на использовании соответствующего ресурса, реализующего интерфейс IDisposable. (В Java теперь есть аналогичный оператор try-with-resources для ресурсов, реализующих AutoCloseable.)

В Java нет риска прерывания потока между назначением и входом в блок try - прерывания происходят только во время ожидания и ожидания. Обновлено: Я не могу найти это в спецификации, что несколько беспокоит. Хм.

Спасибо. Ключевое слово using в C# великолепно, но иногда его нельзя использовать (например, с типом, который не реализует IDisposable, или когда Dispose () следует вызывать условно). Что касается Java, у меня вообще нет опыта с такими проблемами, но нельзя ли прерывать поток?

Hosam Aly 21.01.2009 00:20

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

BlackTigerX 21.01.2009 22:37

Да, но, по крайней мере, они не будут прерваны пост-назначением, предварительным вводом-попыткой-блоком. Это важный момент :)

Jon Skeet 21.01.2009 23:01

Могу я спросить, как вы знаете, что они не будут прерваны между заданием и попыткой?

Hosam Aly 24.01.2009 09:54

@Hosam: Как я уже сказал, мне еще не удалось найти его в спецификации, но обратите внимание, что InterruptedException - это исключение проверил, поэтому его нельзя просто выбросить куда-нибудь. Я считаю, что задокументировано, что где-то будет выбрасываться только во время операций блокировки (ожидание / спящий режим / ввод-вывод и т. д.).

Jon Skeet 24.01.2009 13:12

Спасибо, Джон. Вы как всегда помогаете.

Hosam Aly 25.01.2009 10:22

@Alex: Честно говоря, я не думаю, что это необходимо. Я не вижу никаких признаков того, что кто-то был сбит с толку за более чем 10 лет с момента публикации этого ответа. ОП уже понял это (согласно первому комментарию).

Jon Skeet 10.10.2019 16:37

@Alex: Я отредактирую его - но вы вполне можете найти множество ответов на вопросы о тегах C#, которые предполагают более чем двухдневный опыт работы с C#. (Многие будут говорить о лямбда-выражениях, не уточняя, что это означает, в качестве примера.) Я думаю, что читателям разумно искать любые термины, с которыми они не знакомы - в данном случае «оператор использования» - если только определение термина не является цель вопроса.

Jon Skeet 10.10.2019 16:55

первый предпочтительнее

Другие вопросы по теме