Ну, он не будет утилизирован, так как финализация не является утилизацией.
В System.ComponentModel.Component
есть финализатор, но он подавлен в конструкторе SQLConnection
.Это хорошая идея, если вы наследуете что-то с финализатором, который вы знаете со 100% уверенностью, который вам не понадобится, но плохая идея в противном случае.В этом случае это хорошая идея.
Помните, что SqlConnection
является оберткой для "реального" соединения.Действительно, это, скорее всего, оболочка для изменяющегося набора объектов, которые представляют разные состояния соединения.Это часть механизма, который позволяет эффективно объединять «реальное» соединение, так как каждый раз, когда вы вызываете Open()
, он получает соответствующий объект из пула, и каждый раз, когда вы вызываете Close()
(или напрямую, Dispose()
или, выходя из области действия using
), он возвращает его.
Теперь следует помнить, что только объекты, которые непосредственно содержат неуправляемый ресурс или что-то иное, не относящееся к GC, должны быть завершены.SqlConnection
содержит объект, который может (в зависимости от состояния SqlConnection
) быть объектом, который содержит неуправляемый ресурс (или даже глубже в гнезде классов).Следовательно, нет необходимости в том, чтобы SqlConnection
сама была завершена.Рассмотрим три возможных способа, которыми открытое SqlConnection
может перестать быть открытым SqlConnection
:
Close()
называется.Это немедленно возвращает реальное соединение с пулом (или закрывает его, если нет пула). Dispose()
вызывается.Это вызывает Close()
с тем же эффектом. - Объект получает мусор.
Теперь, в третьем случае, объект содержит ссылку на объект, который имеет реальноеподключение.Это также единственный объект, который делает это.Этот объект, следовательно, также будет собирать мусор.Если у него есть финализатор (что, вероятно, и есть, хотя я не собираюсь предполагать, что дальнейших хитрых трюков не происходит), то этот финализатор заставит его поместить в очередь финализатора, и он будет в конечном итоге завершен.
Если бы SqlConnection
имел финализатор, единственные реальные эффекты были бы:
- Потенциал для глючного кода (работа с финализируемыми членами в коде финализатора чревата, так как вы этого не делаетезнать, были ли они завершены).
- Потенциал для замедления (в любом случае будет установлено настоящее соединение, в лучшем случае мы просто замедляем финализацию и сборщик мусора).
- В любом случае здесь делать нечего (реальное соединение будет завершено без посторонней помощи).
Таким образом, установка финализатора на SqlConnection
- это проигрыш без выигрыша.Кроме того, мы надеемся, что ваше реальное соединение должно быть в конечном итоге завершено.
Это говорит о том, что оно все еще далеко от идеала и все еще очень с вероятностью утечки соединений.Не могли бы вы подробно объяснить, почему вы не можете позвонить Close()
или распорядиться собой?Может ли код, управляющий соединением, не вызывать close для вас (объект должен заканчивать свои дни где-то и должен быть там закрыт)?
Вам нужно поддерживать его в течение IDataReader
или объект, который питается от IDataReader
, который должен быть завершен?В каком случае вы могли бы использовать флаг CommandBehavior.CloseConnection
, чтобы закрытие (или удаление) считывателя закрыло соединение?Этот последний случай является единственным случаем, когда я могу вспомнить, что когда-либо разрешалось, чтобы соединение оставляло область действия неиспользованной.