Некоторые сложные вопросы по оператору using

StackOverflow https://stackoverflow.com/questions/667111

  •  21-08-2019
  •  | 
  •  

Вопрос

Я знаю, что здесь есть несколько тем о том, как использовать оператор using и вызывать метод Dispose().Я прочитал большинство этих тем.

Если я вызываю Dispose(), вызывает ли он Close()?

Если я хочу использовать объект (скажем, SqlDataReader), но затем использовать его снова в другом блоке кода, не следует ли мне вызывать Dispose()?Это также означает опустить оператор использования.

Кроме того, чтобы уточнить, если FileStream оборачивает StreamWriter, и я вызываю метод Dispose для FileStream, это вызовет Flush(), Close() и Dispose() (в зависимости от того, вызывает ли Dispose() Close()) для StreamWriter, верно?Аналогично, если я вызову Close в FileStream, это вызовет только Flush() и Close() в FileStream.

Является ли проверка IL хорошим способом ответить на вопросы о том, что происходит под капотом?

Это было полезно?

Решение

Если я вызываю Dispose(), вызывает ли он Close()?

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

Если я хочу использовать объект (скажем, SqlDataReader), но затем использовать его снова в другом блоке кода, не следует ли мне вызывать Dispose()?Это также означает опустить оператор использования.

Если вы хотите использовать объект снова, вам определенно не следует его удалять.Однако обычно вам следует использовать два отдельных соединения, если вы обращаетесь к базе данных два раза.Обычно не рекомендуется хранить Идатаридер примерно дольше, чем необходимо для получения необходимых данных.

Кроме того, чтобы уточнить, если FileStream оборачивает StreamWriter, и я вызываю метод Dispose для FileStream, это вызовет Flush(), Close() и Dispose() (в зависимости от того, вызывает ли Dispose() Close()) для StreamWriter, верно?Аналогично, если я вызову Close в FileStream, это вызовет только Flush() и Close() в FileStream.

Удаление объекта, который обертывает другой одноразовый объект, должно вызывать Dispose на предмете интерьера.Вызов Close на FileStream позвонит ему Dispose метод под хорошим, поэтому он также будет действовать на оба потока.

Является ли проверка IL хорошим способом ответить на вопросы о том, что происходит под капотом?

Проверка IL определенно ответит на большинство этих вопросов.Как @Богатый говорит, вы также можете просто попробовать отладить свои собственные реализации Dispose.Конечно, есть также документация MSDN, с которой можно начать, прежде чем пытаться разобраться в этом самостоятельно, и Reflector, если вы не хотите возиться с IL.

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

«Если я вызову Dispose(), вызовет ли он Close()?»

Теоретически так и должно быть.Все классы BCL делают это, но автор библиотеки должен правильно с этим справиться.Если используемая вами библиотека выполнена правильно, Dispose() должна также использовать Close() [а Close() будет Dispose() — вызовы должны быть взаимозаменяемыми].

«Если я хочу использовать объект (скажем, SqlDataReader), но затем использовать его снова в другом блоке кода, не следует ли мне вызывать Dispose()?Это также означает опустить оператор использования».

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

«Кроме того, чтобы уточнить, если FileStream оборачивает StreamWriter, и я вызываю метод Dispose для FileStream, это вызовет Flush(), Close() и Dispose() (в зависимости от того, вызывает ли Dispose() Close()) для StreamWriter. , верно?Аналогично, если я вызову Close в FileStream, это вызовет только Flush() и Close() в FileStream».

Если вы оборачиваете FileStream вокруг StreamWriter, я настоятельно рекомендую обращаться с ними последовательно.Используйте один оператор using с обоими членами, чтобы они оба удалялись в конце блока.Это самый безопасный и чистый подход.

«Является ли проверка IL хорошим способом ответить на вопросы о том, что происходит под капотом?»

Это путь – хотя и более трудный путь.Прочтите в MSDN об использовании и потоках, и документация объяснит это более простыми словами, чем попытка анализа IL.Однако, если вам интересно, IL расскажет вам ТОЧНО, что происходит.

Если я вызываю Dispose(), вызывает ли он Close()?

Close() и Dispose() делают то же самое, если они реализованы правильно;это всего лишь наименование.Кажется проще закрыть файл, чем удалить его.Видеть Реализация Finalize и Dispose для очистки неуправляемых ресурсов особенно «Настройка имени метода удаления».

Если я хочу использовать объект (скажем, sqladatareader), но затем используйте его снова в другом блоке кода#, не должен ли я вызовать Dispose ()?Это также означает опустить оператор использования.

Да, потому что объект удаляется при выходе из блока использования.

Кроме того, чтобы уточнить, если FileStream обертывает Strewriter, и я называю Dispose на FileStream, это вызовет flush (), close () и dispose () (в зависимости от того, вызовет ли issos () close ()) на потоковом написании , верно?Аналогично, если я вызову Close в FileStream, > это вызовет только Flush() и Close() в FileStream.

Это другой путь;StreamWriter основан на базовом потоке. Закрытие StreamWriter закрывает базовый поток, который может быть FileStream;увидеть MSDN для справки.Следовательно, достаточно одного оператора использования для StreamWriter.

Если я вызываю Dispose(), вызывает ли он Close()?

Не обязательно.Иногда я использую Reflector, чтобы проверить, что на самом деле происходит в Close and Dispose.

Если я хочу использовать (...) снова в другом блоке кода, не следует ли мне вызывать Dispose()?

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

Как вы сказали, по этому поводу есть много ресурсов, но я включу ссылку MSDN на некоторые рекомендации: Реализация Finalize и Dispose для очистки неуправляемых ресурсов.

Dispose — это основной метод, связанный с интерфейсом IDisposable и шаблоном Disposable.

Microsoft вызывает такой метод, как Close() Специфический псевдоним домена, и это дает идею.Но это все еще зависит от разработчика класса, могут быть различия, например, возможность повторного открытия или нет.Но в целом вас это не должно волновать.

sqlDataReader — немного плохой пример, потому что вы не могу используйте его повторно.В общем, это лучший совет и для всех других одноразовых объектов.

Более простой способ отладить это, чем проходить через код IL, - это получить из вашего IDisposable, переопределить необходимые методы, не делая ничего, кроме вызова base.[Method Name](), и установите точку останова в каждом из них.Затем, если вы поместите производный класс в блок using, вы увидите жизненный цикл этих вызовов.

Нет, IDisposable не требует Close(), но объект, реализующий IDispose, может быть достаточно удобен, чтобы включить его в метод Dispose().

Вам следует избавиться от него, как только у вас появится часть данных, которые вы получаете из БД.Не оставляйте читалку открытой дольше, чем вам нужно.Если вы делаете какие-либо настоящий работайте с данными, используйте dataAdapter/dataset вместо читателя.

Без понятия.Проверьте сгенерированный IL

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top