Является ли вызов Close для класса в предложении using полезным, вредным или спорным?

При рефакторинге некоторого кода я добавил выражение "using", например, так:

using (SerialPort serialPort = new SerialPort())
{
    serialPort.BaudRate = 19200;
    serialPort.Handshake = Handshake.XOnXOff;
    serialPort.Open();
    serialPort.Write(cmd);
    serialPort.Close();
}

... но теперь задаюсь вопросом, могу ли я покончить со звонком в Close. Я полагаю, что так, но это просто изящность (стиль) или истинная необходимость?

4 ответа

Решение

Это действительно зависит от конкретного класса, реализующего IDisposable. Для плохо написанного класса, который реализует IDisposable NOT, вполне возможно правильно высвобождать ресурсы и закрывать соединения. В конкретном случае класса SerialPort в документации говорится, что Close() вызывает Dispose(). Я думаю, что в этом случае вам следует поместить его в блок using и не вызывать Close() вручную.

Это действительно зависит от класса, и если автор реализовал его в соответствии с рекомендациями - реализовал IDisposable правильно, и у Закрыть ничего не делать, кроме как позвонить Dispose(), В таком случае Close() Вызов избыточен и может быть удален при переносе класса в using блок.

Это вообще говоря - в данном конкретном случае с SerialPortони так и сделали, поэтому Close() вызов избыточен и может быть удален.

Согласно Рихтеру:

Типы, которые предлагают возможность детерминированного удаления или закрытия, реализуют шаблон удаления. Шаблон dispose определяет соглашения, которых должен придерживаться разработчик при определении типа, который хочет предложить явную очистку пользователю типа.

Тот факт, что SerialPort определяет открытие и закрытие, подразумевает, что его можно открывать и закрывать несколько раз в течение срока его службы, что взаимно исключает его удаление (например, никогда не используется снова)

Но вернемся к вашему первоначальному вопросу, да - в этом случае это избыточно, декомпиляция объекта SerialPort показывает, что утилита закрывает порт для вас при вызове:

protected override void Dispose(bool disposing)
{
  if (disposing && this.IsOpen)
  {
    this.internalSerialStream.Flush();
    this.internalSerialStream.Close();
    this.internalSerialStream = (SerialStream) null;
  }
  base.Dispose(disposing);
}

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

Если Dispose были единственным методом очистки в обычном случае, тогда подавление исключений представляло бы значительный риск того, что могут возникнуть проблемы, но они останутся незамеченными. Наличие поддержки класса как Close а также usingи клиенты звонят Close в случае основной линии позволит снизить такой риск (если ожидается исключение, Dispose позвонят без Closeи, следовательно, любые исключения при очистке будут подавлены, но код будет знать, что что-то пошло не так из-за ожидающего исключения; если до этого не произошло исключения Closeтот факт, что это не вызывается в Dispose контекст очистки будет означать, что он может предполагать, что ни одно исключение не находится на рассмотрении, и поэтому может безопасно выбрасывать одно из своих)

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

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