Многие думают, что метод Dispose() вызывается внутри метода Close(), поэтому существенной разницы нет! На самом деле эта точка зрения не очень точна.
Действительно, для некоторых классов нет существенной разницы между Close() и Dispose(), но для некоторых классов это не так!
Во-первых, давайте посмотрим на разницу между методом Close() и методом Dispose() класса SqlConnection, который мы используем чаще всего:
Метод Dispose() класса SqlConnection унаследован от класса Component. Исходный код выглядит следующим образом:
общественная недействительность Dispose () {
Dispose(true); //Вызов перегрузки Dispose с параметрами
GC.SuppressFinalize(this); //Просим систему не вызывать финализатор указанного объекта.
}
protected virtual void Dispose(bool dispositing) {
если (удаление) {
блокировка(это) {
if (site != null && site.Container != null) {
сайт.Контейнер.Удалить(это);
}
если (события != ноль) {
Обработчик EventHandler = (EventHandler)events[EventDispose];
if (обработчик!= null) handler(this, EventArgs.Empty);
}
}
}
}
Описание метода Close() класса SqlConnection в MSDN выглядит следующим образом:
Закройте соединение с базой данных. Это предпочтительный метод закрытия любого открытого соединения. Если SqlConnection выходит за пределы области действия, он не будет закрыт. потому что
Поэтому соединение необходимо закрыть явно, вызвав Close или Dispose. Close и Dispose функционально эквивалентны. Если значение пула соединений
Объединение в пулы Если установлено значение true или Yes, базовое соединение будет возвращено в пул соединений. С другой стороны, если для пула установлено значение «ложь» или «нет», тогда
Базовое соединение с сервером закрыто.
Из описания кажется, что метод Close() и метод Dispose() похожи. На самом деле они эквивалентны только в функции закрытия соединения.
() исходный код метода:
переопределить public void Close() {
ИнтПтр hscp;
Bid.ScopeEnter(out hscp, "<sc.SqlConnection.Close|API> %d#" , ObjectID);
пытаться {
Статистика SqlStatistics = null;
RuntimeHelpers.PrepareConstrainedRegions();
пытаться {
#if ОТЛАДКА
объект InitialReliabilitySlotValue = Thread.GetData(TdsParser.ReliabilitySlot);
RuntimeHelpers.PrepareConstrainedRegions();
пытаться {
Thread.SetData(TdsParser.ReliabilitySlot, true);
#endif //ОТЛАДКА
статистика = SqlStatistics.StartTimer(Статистика);
// Блокировка здесь предназначена для защиты от команды command.cancel/connection.close
состояние гонки
// SqlInternalConnectionTds устанавливается на OpenBusy во время закрытия, как только это
что произойдет, приведенный ниже актерский состав потерпит неудачу и
// команду больше нельзя будет отменить. Возможно, это будет желательно.
можно отменить операцию закрытия, но это
// вне области действия Whidbey RTM. Другие сведения см. в (SqlCommand::Cancel).
замок.
блокировка (InnerConnection) {
InnerConnection.CloseConnection(это, ConnectionFactory);
}
// не требует GC.KeepAlive(this) из-за OnStateChange
if (ноль != Статистика) {
ADP.TimerCurrent(out _statistics._closeTimestamp);
}
#if ОТЛАДКА
}
окончательно {
Thread.SetData(TdsParser.ReliabilitySlot, InitialReliabilitySlotValue);
}
#endif //ОТЛАДКА
}
catch (System.OutOfMemoryException e) {
Прервать(е);
бросать;
}
catch (System.StackOverflowException e) {
Прервать(е);
бросать;
}
catch (System.Threading.ThreadAbortException e) {
Прервать(е);
бросать;
}
окончательно {
SqlStatistics.StopTimer(статистика);
}
}
окончательно {
SqlDebugContext SDC = _sdc;
_sdc = ноль;
Bid.ScopeLeave(ref hscp);
если (sdc != ноль) {
sdc.Dispose();
}
}
}
Вы можете видеть, что метод Close() не вызывает метод Dispose(). Несмотря на наличие строки sdc.Dispose();, она освобождает только SqlDebugContext.
Экземпляр не имеет ничего общего с методом SqlConnection.Dispose()!
Так в чем же разница?
Метод Close() только закрывает соединение, а затем соединение сохраняется в пуле соединений, поэтому после вызова метода Close() вы все равно можете передать
Open(), чтобы открыть соединение, и после вызова метода Dispose() соединение больше нельзя использовать!
Еще одно важное отличие заключается в том, что когда метод Close() не вызывает GC.SuppressFinalize(this);, прямым следствием этого является мусор.
Во время переработки требуются операции завершения, что приведет к увеличению «возраста поколения» этого экземпляра, тем самым значительно задерживая время переработки этого объекта!
Для класса SqlConnection, если вам понадобится использовать это соединение в будущем, вы можете использовать метод Close(), чтобы временно закрыть соединение.
Чтобы использовать это соединение, вы можете сначала использовать метод Dispose() для освобождения ресурсов. Конечно, вы можете использовать ключевое слово using, чтобы упростить этот процесс.
Я не нашел исходного кода класса OleDbConnection и класса OdbcConnection, но они должны быть похожи на класс SqlConnection!
Давайте посмотрим на часто используемый класс и увидим разницу между методом Close() и методом Dispose() класса FileStream:
Метод Close() класса FileStream унаследован от класса Stream. Исходный код выглядит следующим образом:
публичная виртуальная пустота Close()
{
Утилизировать (правда);
GC.SuppressFinalize(это);
}
Метод Dispose() класса FileStream унаследован от класса Stream. Исходный код выглядит следующим образом:
публичная недействительность Dispose()
{
Закрывать();
}
Это реализация стандартного режима Dispose. Метод Close() вызывает метод Dispose с параметрами, а затем вызывает GC.SuppressFinalize.
(this); Просит систему не вызывать финализатор указанного объекта. Метод Dispose() напрямую вызывает метод Close()!
Для класса FileStream нет никакой разницы между методами Close() и Dispose()!