Я считаю это злоупотреблением оператором using. Знаю, что на этой должности я в меньшинстве.
Я считаю это злоупотреблением по трем причинам.
Во-первых, потому что я ожидаю, что "using" используется для использования ресурса и удаления его, когда вы закончите с ним . Изменение государственной программы не используя ресурс и изменить его обратно не распоряжаться ничего. Следовательно, «использование» для изменения и восстановления состояния является злоупотреблением; код вводит в заблуждение случайного читателя.
Во-вторых, потому что я ожидаю, что слово «использование» будет использоваться из вежливости, а не по необходимости . Причина, по которой вы используете "using" для удаления файла, когда вы закончите с ним, не потому, что это необходимо сделать, а потому, что это вежливо - кто-то другой может ждать, чтобы использовать этот файл, поэтому сказал "готово сейчас "- это нравственно правильный поступок. Я ожидаю, что я смогу провести рефакторинг «using», чтобы использованный ресурс удерживался дольше и утилизировался позже, и что единственное влияние этого - небольшое неудобство для других процессов . Блок "использования", который имеет семантическое влияние на состояние программы. является оскорбительным, потому что он скрывает важную, необходимую мутацию состояния программы в конструкции, которая выглядит так, как будто она существует для удобства и вежливости, а не по необходимости.
И в-третьих, действия вашей программы определяются ее состоянием; необходимость осторожного манипулирования состоянием - вот почему мы впервые ведем этот разговор. Давайте рассмотрим, как мы можем проанализировать вашу исходную программу.
Если бы вы принесли это на проверку кода в моем офисе, первый вопрос, который я бы задала, будет: «Действительно ли правильно блокировать блокировку, если возникает исключение?» Из вашей программы явно очевидно, что эта штука агрессивно повторно блокирует блокировку, что бы ни случилось. Это правильно? Возникло исключение. Программа находится в неизвестном состоянии. Мы не знаем, выбросили ли Foo, Fiddle или Bar, почему они выбросили или какие мутации они произвели в другом состоянии, которое не было очищено. Сможете ли вы убедить меня, что в этой ужасной ситуации всегда будет правильным сделать повторную блокировку?
Может быть, а может и нет. Я хочу сказать, что с кодом, который был изначально написан, рецензент знает, что нужно задать вопрос . С кодом, который использует "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 заблокирован, но до того, как будет введена область с защитой от попытки, связанная с использованием. Но с версией "с использованием" я предполагаю, что это "ну и что?" ситуация. Очень жаль, если это произойдет, но я предполагаю, что «использование» используется только для вежливости, а не для изменения жизненно важного состояния программы. Я предполагаю, что если какое-то ужасное исключение прерывания потока произойдет точно в неподходящее время, тогда, ну что ж, сборщик мусора в конечном итоге очистит этот ресурс, запустив финализатор.