Algum sentido para definir obj = null (Nothing) em Dispose ()?

Existe algum sentido para definir o object personalizado como null ( Nothing in VB.NET) no método Dispose() ? Isso poderia impedir vazamentos de memory ou é inútil?

Vamos considerar dois exemplos:

 public class Foo : IDisposable { private Bar bar; // standard custom .NET object public Foo(Bar bar) { this.bar = bar; } public void Dispose() { bar = null; // any sense? } } public class Foo : RichTextBox { // this could be also: GDI+, TCP socket, SQl Connection, other "heavy" object private Bitmap backImage; public Foo(Bitmap backImage) { this.backImage = backImage; } protected override void Dispose(bool disposing) { if (disposing) { backImage = null; // any sense? } } } 

   

O objective do Dispose() é permitir a limpeza de resources que não são manipulados pelo coletor de lixo. Objetos são atendidos pelo GC, então não há realmente necessidade de definir a referência para null em circunstâncias normais.

A exceção é se você espera que o chamador chame Dispose e segure a instância depois disso. Nesse caso, pode ser uma boa ideia definir a referência interna como nula. No entanto, instâncias descartáveis ​​são normalmente descartadas e liberadas ao mesmo tempo. Nestes casos, não fará uma grande diferença.

Pessoalmente tenho tendência para; por dois motivos:

  • isso significa que se alguém esqueceu de liberar o Foo (talvez de um evento), qualquer object downstream (um Bitmap neste caso) ainda pode ser coletado (em algum momento no futuro – sempre que o GC se sentir assim); É provável que este seja apenas um invólucro superficial em torno de um recurso não gerenciado, mas cada pequena ajuda.
    • Eu realmente não gosto de manter acidentalmente um gráfico inteiro de objects por aí porque o usuário esqueceu de desengatar um evento; IDisposable é um prático “quase-kill” switch – por que não separar tudo disponível?
  • mais importante, eu posso descaradamente agora usar este campo para verificar (em methods etc) para eliminação, jogando um ObjectDisposedException se for null

É quase inútil. A configuração para NULL de volta nos dias COM / VB antigos, acredito, diminuiria sua contagem de referência.

Isso não é verdade com o .NET. Quando você define bar como null, você não está destruindo ou liberando nada. Você está apenas alterando a referência para a qual a barra aponta, do seu object para “nulo”. Seu object ainda existe (embora agora, como nada se refere a ele, ele será eventualmente coletado como lixo). Com poucas exceções, e na maioria dos casos, isso é a mesma coisa que teria acontecido se você não tivesse feito Foo IDisposable em primeiro lugar.

O grande objective do IDisposable é permitir que você libere resources não gerenciados , como sockets TCP ou conexões SQL, ou o que for. Isso geralmente é feito chamando qualquer function de limpeza que o recurso não gerenciado fornece, não definindo a referência como “nula”.

Isso pode fazer sentido se você quiser de alguma forma impedir que a instância de propriedade descartada seja reutilizada.

Quando você define referências a campos descartáveis ​​como null, é garantido que você não usará mais as instâncias.

Você não obterá ObjectDisposedException ou qualquer outro estado inválido causado pelo uso da instância descartada (você poderá obter NullReferenceException se não verificar nulos).

Isso pode não fazer sentido para você, contanto que todos os objects IDisposable tenham uma propriedade IsDisposed e / ou ObjectDisposedException se forem usados ​​depois de serem descartados – alguns podem violar esse princípio e defini-los como nulos podem impedir que efeitos indesejados ocorram.

Em c #, definir um object como nulo é apenas liberar a referência ao object.

Portanto, é teoricamente melhor liberar a referência em objects gerenciados em um Dispose-Method em C #, mas apenas para a possibilidade de o GC coletar o object referenciado antes que o object descartado seja coletado. Como ambos provavelmente serão coletados na mesma execução, o GC provavelmente reconhecerá que o object referenciado é referenciado apenas por um tipo descartado, portanto ambos podem ser coletados.

Também a necessidade de liberar a referência é muito pequena, já que todos os membros públicos de sua class descartável devem lançar uma exceção se a class já estiver descartada. Portanto, nenhum access ao seu object referenciado seria bem-sucedido depois de descartar o método referenciado.

No VB.NET,sentido em definir objects Nothing Private WithEvents declarados.

Os manipuladores que usam a palavra-chave Handles serão removidos dessa maneira a partir desses objects.

A finalidade do dispose() é limpar os resources que não são gerenciados. Conexões TCP, conexões de database e outros objects de database e muitos desses resources não gerenciados devem ser liberados pelo desenvolvedor no método de descarte. Então isso realmente faz sentido.

Em geral, não há necessidade de definir como nulo. Mas suponha que você tenha uma funcionalidade de redefinição em sua class.

Então você pode fazer, porque você não quer chamar de dispor duas vezes, uma vez que alguns dos Dispose não podem ser implementados corretamente e lançar exceção System.ObjectDisposed.

 private void Reset() { if(_dataset != null) { _dataset.Dispose(); _dataset = null; } //..More such member variables like oracle connection etc. _oraConnection }