Я считаю, что это злоупотребление утверждением об использовании. Мне известно, что я нахожусь в меньшинстве на этой должности.
Я считаю это злоупотреблением по трем причинам.
Во-первых, потому что я ожидаю, что «использование» используется для использования ресурса и распоряжается им, когда вы закончите с ним . Изменение состояния программы не означает с использованием ресурса , а его изменение обратно не означает удаление чего-либо. Следовательно, «использование» для изменения и восстановления состояния является злоупотреблением; код вводит в заблуждение случайного читателя.
Во-вторых, потому что я ожидаю, что «использование» будет использоваться из вежливости, а не по необходимости . Причина, по которой вы используете «использование» для удаления файла, когда вы закончили с ним, не в том, что необходимо , чтобы сделать это, а в том, что он вежлив - кто-то другой возможно, вы ждете, чтобы использовать этот файл, поэтому сказать «сделано сейчас» - это морально правильная вещь. Я ожидаю, что смогу реорганизовать «использование» так, чтобы использованный ресурс удерживался дольше, а потом утилизировался, и что единственное влияние этого - слегка затруднить другие процессы . Блок "using", который семантически влияет на состояние программы , является оскорбительным, потому что он скрывает важную, требуемую мутацию состояния программы в конструкции, которая выглядит так, как будто она предназначена для удобства и вежливости, а не необходимости.
И в-третьих, действия вашей программы определяются ее состоянием; Необходимость осторожного манипулирования государством - именно поэтому мы ведем этот разговор в первую очередь. Давайте рассмотрим, как мы можем проанализировать вашу оригинальную программу.
Если бы вы принесли это на рассмотрение кода в моем офисе, первый вопрос, который я бы задал: "Действительно ли правильно заблокировать ошибку, если возникнет исключение?" Из вашей программы совершенно очевидно, что эта штука агрессивно блокирует ошибку независимо от того, что происходит. Это правильно? Исключение было сгенерировано. Программа находится в неизвестном состоянии. Мы не знаем, бросили ли Фу, Фиддл или Бар, почему они бросили, или какие мутации они выполнили в другом состоянии, которые не были очищены. Можете ли вы убедить меня, что в этой ужасной ситуации всегда - правильная вещь, которую нужно сделать, чтобы снова заблокировать?
Может быть, а может и нет. Я хочу сказать, что с кодом, как он был изначально написан, рецензент кода знает, как задать вопрос . С кодом, который использует «использование», я не знаю, чтобы задать вопрос; Я предполагаю, что блок «using» выделяет ресурс, использует его некоторое время и вежливо избавляется от него, когда это сделано, а не то, что закрывающая скобка блока «using» мутирует мой состояние программы в исключительных обстоятельствах, когда произвольно много условий согласованности состояния программы были нарушены.
Использование блока «using» для семантического эффекта приводит к фрагменту этой программы:
}
чрезвычайно значимый. Когда я смотрю на эту единственную близкую скобку, я не сразу думаю, что «эта скобка имеет побочные эффекты, которые имеют далеко идущие последствия для глобального состояния моей программы». Но когда вы злоупотребляете «использованием» подобным образом, вдруг это происходит.
Второе, что я хотел бы спросить, если бы увидел исходный код, это "что произойдет, если возникнет исключение после разблокировки, но до ввода попытки?" Если вы запускаете неоптимизированную сборку, компилятор мог вставить инструкцию no-op перед попыткой, и возможно возникновение исключения прерывания потока в no-op. Это редко, но это случается в реальной жизни, особенно на веб-серверах. В этом случае разблокировка происходит, но блокировка никогда не происходит, потому что перед попыткой возникло исключение. Вполне возможно, что этот код уязвим для этой проблемы, и на самом деле должен быть написан
bool needsLock = false;
try
{
// must be carefully written so that needsLock is set
// if and only if the unlock happened:
this.Frobble.AtomicUnlock(ref needsLock);
blah blah blah
}
finally
{
if (needsLock) this.Frobble.Lock();
}
Опять, может быть, может и нет, но Я знаю, чтобы задать вопрос . С версией «using» она подвержена той же проблеме: исключение прерывания потока может быть вызвано после того, как Frobble заблокирован, но до того, как будет введена защищенная от попыток область, связанная с использованием. Но с версией «использую», я предполагаю, что это «ну и что?» ситуация. К сожалению, если это произойдет, но я предполагаю, что «использование» только для того, чтобы быть вежливым, а не изменять жизненно важное состояние программы. Я предполагаю, что если какое-то ужасное исключение прерывания потока произойдет точно в неподходящее время, то, ну, в общем, сборщик мусора очистит этот ресурс в конечном итоге, запустив финализатор.