none
IDisposable RRS feed

  • Pergunta

  • Qual a vantagem de referenciar a interface IDisposable nas minhas classes?

     

    Ele ajuda a chamar o garbage collector mais rapidamente para liberar recursos da memória? Ou ainda tenho que explicitar o dispose de cada objeto declarado nessa minha classe?

     

    Em que tipo de classes devo usar essa interface? Todas? Algumas? Quais?

     

    Obrigado

    quinta-feira, 24 de novembro de 2011 19:47

Respostas

  • Ola Marcio,

    Na verdade o metodo dispose é usado para liberar recursos alocados dentro de sua classe... por exemplo... vc tem uma classe que tem uma propriedade privada que é uma SqlConnection... e vc quer garantir que quando o Garbage Collector vier remover esse recurso da memoria.... que essa conexão (se tiver aberta) seja corretamente encerrada e desalocada.

    Isso acontece principalmente quando se usa um controle ActiveX dentro da classe... o Garbage Collector sozinho não saberia quando liberar corretamente esse objeto da memória, mas se vc implementar o mesmo dentro do seu Dispose, ai sim vc estaria garantindo a forma correta de liberar o recurso não gerenciado.

    Alem disso, tambem é util para que um programador que venha a utilizar esse seu objeto saber que exite alguma coisa dentro daquela classe que devera ser devidamente desalocada... ai entra o uso de um try/finally... ou mais simplesmente o using....

    Então, sendo um pouco redundante, você deverá usar a interface IDisposable, sempre que vc tiver usando um recurso dentro de sua classe que deverá ser finalizado corretamente quando o GC for dispensar essa classe.

    Da uma olhada na descrição mais detalhada do assunto aqui: http://msdn.microsoft.com/pt-br/library/fs2xkftw.aspx

    • Sugerido como Resposta hamiltonj sexta-feira, 25 de novembro de 2011 16:38
    • Marcado como Resposta Eder CostaModerator terça-feira, 6 de dezembro de 2011 14:05
    quinta-feira, 24 de novembro de 2011 23:47
    Moderador
  • Ola Marcio,

    Bem... digamos que voce queira manter uma unica instancia de conexão na sua classe DAO.... voce teria algo mais ou menos assim:

     

    public class MinhaDAO {
    	private readonly DbConnection connection;
    	
    	public MinhaDAO() {
    		connection = new DbConnection("...");
    		connection.Open();
    	}
    
    	public void IncluirObjetoA(ObjetoA obj) {
    		// Inlcuir obj usando connection
    	}
    
    	public void IncluirObjetoB(ObjetoB obj) {
    		// Inlcuir obj usando connection
    	}
    }
    

     


    Vai acontecer que em determinado momento... a sua instancia de MinhaDAO vai ser coletada pelo GC... mas a instancia de connection pode se manter ativa e aberta, pq não foi finalizada....

    Ai entra o IDisposable:

     

    public class MinhaDAO: IDisposable {
    	private readonly DbConnection connection;
    	
    	public MinhaDAO() {
    		InitalizeConnection();
    	}
    
    	public void IncluirObjetoA(ObjetoA obj) {
    		// Inlcuir obj usando connection
    	}
    
    	public void IncluirObjetoB(ObjetoB obj) {
    		// Inlcuir obj usando connection
    	}
    
    	public override Dispose() {
    		this.dispose(true);
    	}
    
    	protected virtual void Dispose(bool disposable) {
    		if (disposable) {
    			DisposeConnection();
    		}
    
    		GC.SurpressFinalize(this);
    	}
    
    	private void InitalizeConnection() {
    		connection = new DbConnection("...");
    		connection.Open();
    	}	
    
    	private void DisposeConnection() {
    		if (connection != null) {
    			if (connection.State = ConnectionState.Opened) connection.Close();
    			connection.Dispose();
    		}
    	}
    }
    

     


    Desta forma eu estou garantindo a liberação dos recursos utilizados na minha classe MinhaDao corretamente na finalização da mesma...

    Lembrando que o principal foco são as chamadas a objetos COM que não são liberado pelo GC, ou mesmo chamadas externas como as APIs do windows... quando se usa ponteiros (handles) de memoria,...

    Mas sempre chame os metodos .NET que tenham dispose no seu dispose (se vc não usar o mesmo no escopo do metodo... ai  não precisa da interface IDisposable...) pq esses objetos que tem o Dispose fazem em algum momento o uso de um objeto COM ou não-gerenciado que tem q ser liberado corretamente...

    Se seus objetos não tem nenhuma propriedade que não seje devidamente liberada no termino de seu uso, não precisa do Dispose...

    domingo, 27 de novembro de 2011 19:59
    Moderador

Todas as Respostas

  • Ola Marcio,

    Na verdade o metodo dispose é usado para liberar recursos alocados dentro de sua classe... por exemplo... vc tem uma classe que tem uma propriedade privada que é uma SqlConnection... e vc quer garantir que quando o Garbage Collector vier remover esse recurso da memoria.... que essa conexão (se tiver aberta) seja corretamente encerrada e desalocada.

    Isso acontece principalmente quando se usa um controle ActiveX dentro da classe... o Garbage Collector sozinho não saberia quando liberar corretamente esse objeto da memória, mas se vc implementar o mesmo dentro do seu Dispose, ai sim vc estaria garantindo a forma correta de liberar o recurso não gerenciado.

    Alem disso, tambem é util para que um programador que venha a utilizar esse seu objeto saber que exite alguma coisa dentro daquela classe que devera ser devidamente desalocada... ai entra o uso de um try/finally... ou mais simplesmente o using....

    Então, sendo um pouco redundante, você deverá usar a interface IDisposable, sempre que vc tiver usando um recurso dentro de sua classe que deverá ser finalizado corretamente quando o GC for dispensar essa classe.

    Da uma olhada na descrição mais detalhada do assunto aqui: http://msdn.microsoft.com/pt-br/library/fs2xkftw.aspx

    • Sugerido como Resposta hamiltonj sexta-feira, 25 de novembro de 2011 16:38
    • Marcado como Resposta Eder CostaModerator terça-feira, 6 de dezembro de 2011 14:05
    quinta-feira, 24 de novembro de 2011 23:47
    Moderador
  • Rui,

    Dentro da minha classe DAL de acesso ao banco eu já uso using para abrir minha conexão, e até onde sei, após ser executado todo o código dentro do bloco, é efetuado o close e dispose nessa minha conexão. Então nesse caso eu ainda preciso chamar a interface IDisposable?

    Ainda não entendi direito para que serve referenciar essa interface. Ela me obriga a dar close e dispose em todos os objetos dentro dessa minha classe?

    sexta-feira, 25 de novembro de 2011 12:01
  • Uma vez que sua classe de nome ConnWrapper (exemplo) implementa IDisposable, você não precisaria expor o método Close para fechar a conexão, por exemplo.

    Bastaria você usar o pattern using, como por exemplo:

    using(var wrapper = new ConnWrapper())

    {

          wrapper.MetodoX();

    }

    Quando a execução sair do escopo do using, o Dispose da classe ConnWrapper será invocado automaticamente e dentro do método Dispose, o Close de seu objeto Connection deverá ser invocado.

    Espero que tenha compreendido dessa vez.

    Abraço.


    HJ
    sexta-feira, 25 de novembro de 2011 16:41
  • Ola Marcio,

    Bem... digamos que voce queira manter uma unica instancia de conexão na sua classe DAO.... voce teria algo mais ou menos assim:

     

    public class MinhaDAO {
    	private readonly DbConnection connection;
    	
    	public MinhaDAO() {
    		connection = new DbConnection("...");
    		connection.Open();
    	}
    
    	public void IncluirObjetoA(ObjetoA obj) {
    		// Inlcuir obj usando connection
    	}
    
    	public void IncluirObjetoB(ObjetoB obj) {
    		// Inlcuir obj usando connection
    	}
    }
    

     


    Vai acontecer que em determinado momento... a sua instancia de MinhaDAO vai ser coletada pelo GC... mas a instancia de connection pode se manter ativa e aberta, pq não foi finalizada....

    Ai entra o IDisposable:

     

    public class MinhaDAO: IDisposable {
    	private readonly DbConnection connection;
    	
    	public MinhaDAO() {
    		InitalizeConnection();
    	}
    
    	public void IncluirObjetoA(ObjetoA obj) {
    		// Inlcuir obj usando connection
    	}
    
    	public void IncluirObjetoB(ObjetoB obj) {
    		// Inlcuir obj usando connection
    	}
    
    	public override Dispose() {
    		this.dispose(true);
    	}
    
    	protected virtual void Dispose(bool disposable) {
    		if (disposable) {
    			DisposeConnection();
    		}
    
    		GC.SurpressFinalize(this);
    	}
    
    	private void InitalizeConnection() {
    		connection = new DbConnection("...");
    		connection.Open();
    	}	
    
    	private void DisposeConnection() {
    		if (connection != null) {
    			if (connection.State = ConnectionState.Opened) connection.Close();
    			connection.Dispose();
    		}
    	}
    }
    

     


    Desta forma eu estou garantindo a liberação dos recursos utilizados na minha classe MinhaDao corretamente na finalização da mesma...

    Lembrando que o principal foco são as chamadas a objetos COM que não são liberado pelo GC, ou mesmo chamadas externas como as APIs do windows... quando se usa ponteiros (handles) de memoria,...

    Mas sempre chame os metodos .NET que tenham dispose no seu dispose (se vc não usar o mesmo no escopo do metodo... ai  não precisa da interface IDisposable...) pq esses objetos que tem o Dispose fazem em algum momento o uso de um objeto COM ou não-gerenciado que tem q ser liberado corretamente...

    Se seus objetos não tem nenhuma propriedade que não seje devidamente liberada no termino de seu uso, não precisa do Dispose...

    domingo, 27 de novembro de 2011 19:59
    Moderador