Muitas pessoas pensam que o método Dispose() é chamado internamente no método Close(), portanto não há diferença essencial! Na verdade, esta visão não é muito precisa.
Para algumas classes, é verdade que não há diferença essencial entre Close() e Dispose(), mas para algumas classes este não é o caso!
Primeiro, vamos ver a diferença entre o método Close() e o método Dispose() de SqlConnection que usamos com mais frequência:
O método Dispose() da classe SqlConnection é herdado da classe Component. O código-fonte é o seguinte:
public void Dispose() {
Dispose(true); //Chama uma sobrecarga de Dispose com parâmetros
GC.SuppressFinalize(this); //Solicita ao sistema para não chamar o finalizador do objeto especificado.
}
virtual void protegido Dispose(bool disposing) {
if (descartando) {
bloquear(este) {
if (site! = null && site.Container! = null) {
site.Container.Remove(isto);
}
if (eventos! = nulo) {
Manipulador EventHandler = (EventHandler)events[EventDisposed];
if (manipulador! = nulo) manipulador (this, EventArgs.Empty);
}
}
}
}
A descrição do método Close() da classe SqlConnection no MSDN é a seguinte:
Feche a conexão com o banco de dados. Este é o método preferido para fechar qualquer conexão aberta. Se o SqlConnection sair do escopo, ele não será fechado. porque
Portanto, a conexão deve ser fechada explicitamente chamando Close ou Dispose. Close e Dispose são funcionalmente equivalentes. Se o valor do pool de conexões
Pooling Se definido como verdadeiro ou sim, a conexão subjacente será retornada ao pool de conexões. Por outro lado, se Pooling estiver definido como falso ou não, então
A conexão subjacente com o servidor está fechada.
Pela descrição, parece que o método Close() e o método Dispose() são semelhantes. Na verdade, eles são equivalentes apenas na função de fechar a conexão.
() código-fonte do método:
substituir public void Close() {
IntPtr hscp;
Bid.ScopeEnter(out hscp, "<sc.SqlConnection.Close|API> %d#" , ObjectID);
tentar {
Estatísticas SqlStatistics = null;
RuntimeHelpers.PrepareConstrainedRegions();
tentar {
#if DEBUGAR
objeto inicialReliabilitySlotValue = Thread.GetData(TdsParser.ReliabilitySlot);
RuntimeHelpers.PrepareConstrainedRegions();
tentar {
Thread.SetData(TdsParser.ReliabilitySlot, verdadeiro);
#endif //DEBUGAR
estatísticas = SqlStatistics.StartTimer(Estatísticas);
// O bloqueio aqui é para proteger contra o comando.cancel/connection.close
condição de corrida
// O SqlInternalConnectionTds é definido como OpenBusy durante o fechamento, uma vez que este
o que acontece o elenco abaixo irá falhar e
// o comando não será mais cancelável. Pode ser desejável que seja.
capaz de cancelar a operação de fechamento, mas isso é
// fora do escopo do Whidbey RTM Consulte (SqlCommand::Cancel) para outros.
trancar.
bloquear (InnerConnection) {
InnerConnection.CloseConnection(this, ConnectionFactory);
}
// não requer GC.KeepAlive(this) por causa de OnStateChange
if (nulo! = Estatísticas) {
ADP.TimerCurrent(out _statistics._closeTimestamp);
}
#if DEBUGAR
}
finalmente {
Thread.SetData(TdsParser.ReliabilitySlot, inicialReliabilitySlotValue);
}
#endif //DEBUGAR
}
pegar (System.OutOfMemoryException e) {
Abortar(e);
lançar;
}
pegar (System.StackOverflowException e) {
Abortar(e);
lançar;
}
pegar (System.Threading.ThreadAbortException e) {
Abortar(e);
lançar;
}
finalmente {
SqlStatistics.StopTimer(estatísticas);
}
}
finalmente {
SqlDebugContext sdc = _sdc;
_sdc = nulo;
Bid.ScopeLeave(ref hscp);
if (sdc! = nulo) {
sdc.Dispose();
}
}
}
Você pode ver que o método Close() não chama o método Dispose(). Embora exista uma linha de sdc.Dispose();, isso apenas libera o SqlDebugContext.
Por exemplo, não tem nada a ver com o método SqlConnection.Dispose()!
Então qual é a diferença?
O método Close() apenas fecha a conexão e, em seguida, a conexão é armazenada no pool de conexões, portanto, após chamar o método Close(), você ainda pode passar
Método Open() para abrir a conexão e após chamar o método Dispose(), a conexão não pode mais ser usada!
Outra diferença importante é que quando o método Close() não chama GC.SuppressFinalize(this);, a consequência direta disso é lixo.
São necessárias operações de terminação durante a reciclagem, o que fará com que a “idade de geração” desta instância aumente, atrasando muito o tempo de reciclagem deste objeto!
Para a classe SqlConnection, se precisar usar essa conexão no futuro, você pode usar o método Close() para fechar temporariamente a conexão.
Para usar esta conexão, você pode primeiro usar o método Dispose() para liberar recursos. Claro, você pode usar a palavra-chave using para simplificar esse processo.
Não encontrei o código fonte da classe OleDbConnection e da classe OdbcConnection, mas devem ser semelhantes à classe SqlConnection!
Vejamos uma classe comumente usada e vejamos a diferença entre o método Close() e o método Dispose() da classe FileStream:
O método Close() da classe FileStream é herdado da classe Stream. O código-fonte é o seguinte:
vazio virtual público Fechar()
{
Dispor(verdadeiro);
GC.SuppressFinalize(este);
}
O método Dispose() da classe FileStream é herdado da classe Stream. O código-fonte é o seguinte:
público vazio Dispose()
{
Fechar();
}
É uma implementação do modo Dispose padrão. O método Close() chama o método Dispose com parâmetros e, em seguida, chama GC.SuppressFinalize.
(this); Solicita ao sistema para não chamar o finalizador do objeto especificado. O método Dispose() chama diretamente o método Close()!
Para a classe FileStream, não há diferença entre o método Close() e o método Dispose()!