Pergunta

Você deve definir todos os objetos para null (Nothing no VB.NET) depois de ter terminado com ela?

Eu entendo que .NET é essencial dispor de todas as instâncias de objetos que implementam a IDisposable interface para liberar alguns recursos, embora o objeto ainda pode ser algo depois da eliminação (daí o isDisposed propriedade em formulários), então eu suponho que ele ainda pode permanecer na memória ou pelo menos em parte?

Também sei que, quando um objeto sai de escopo, em seguida, marcado para coleta pronto para a próxima passagem do coletor de lixo (apesar de que isso pode levar tempo).

Então, com isso em mente será a sua definição para null acelerar o sistema liberar a memória como ele não tem de trabalhar para fora que ele não está mais no escopo e são eles quaisquer efeitos colaterais ruins?

Artigos de MSDN nunca faça isso em exemplos e, atualmente, eu faço isso porque eu não posso ver o mal.No entanto me deparei com uma mistura de opiniões assim que todos os comentários são úteis.

Foi útil?

Solução

Karl é absolutamente correto, não há nenhuma necessidade para definir os objetos para null após o uso.Se um objeto implementa IDisposable, apenas certifique-se de que você chamar IDisposable.Dispose() quando você é feito com o objeto (envolto em uma try..finally, ou, de uma using() bloco).Mas mesmo se você não se lembra de chamar Dispose(), o finaliser método sobre o objeto deve ser chamado Dispose() para você.

Eu pensei que este era um bom tratamento:

Cavando em IDisposable

e este

A Compreensão IDisposable

Não há nenhum ponto em tentar adivinhar o GC e suas estratégias de gestão, porque é auto-ajuste e opaco.Houve uma boa discussão sobre o funcionamento interno com Jeffrey Richter em Dot Net Rochas aqui: Jeffrey Richter no Modelo de Memória do Windows e Richters livro CLR através de C# capítulo 20 tem um ótimo tratamento:

Outras dicas

Outra razão para evitar a criação de objetos nulos quando você está feito com eles é que, na verdade, pode mantê-los vivos por mais tempo.

exemplo:

void foo()
{
    var someType = new SomeType();
    someType.DoSomething();
    // someType is now eligible for garbage collection         

    // ... rest of method not using 'someType' ...
}

vai permitir que o objeto referenciado pelo someType para ser GC seria após a chamada para "DoSomething", mas

void foo()
{
    var someType = new SomeType();
    someType.DoSomething();
    // someType is NOT eligible for garbage collection yet
    // because that variable is used at the end of the method         

    // ... rest of method not using 'someType' ...
    someType = null;
}

às vezes, pode manter o objeto vivo até o fim do método.O JIT geralmente otimizado de distância a atribuição para null, para ambos os bits de código acabam sendo o mesmo.

Não não nulo objetos.Você pode verificar para fora do http://codebetter.com/blogs/karlseguin/archive/2008/04/27/foundations-of-programming-pt-7-back-to-basics-memory.aspx para obter mais informações, mas a criação de coisas para null não fazer nada, exceto suja seu código.

Também:

using(SomeObject object = new SomeObject()) 
{
  // do stuff with the object
}
// the object will be disposed of

Em geral, não há necessidade de objetos nulos após o uso, mas em alguns casos eu acho que é uma boa prática.

Se um objeto implementa IDisposable e é armazenado em um campo, eu acho que é bom para null, apenas para evitar o uso do objeto descartado.Os erros de classificação a seguir pode ser doloroso:

this.myField.Dispose();
// ... at some later time
this.myField.DoSomething();

É bom nulo o campo após a eliminação, e obter um NullPtrEx direita da linha onde o campo é usado novamente.Caso contrário, você pode se deparar com alguns enigmática bug para baixo da linha (dependendo exatamente o que DoSomething faz).

As Chances são de que seu código não é estruturado com força suficiente, se você sentir a necessidade de null variáveis.

Há um número de maneiras para limitar o escopo de uma variável:

Como mencionado por Steve Tranby

using(SomeObject object = new SomeObject()) 
{
  // do stuff with the object
}
// the object will be disposed of

Da mesma forma, você pode simplesmente usar parênteses:

{
    // Declare the variable and use it
    SomeObject object = new SomeObject()
}
// The variable is no longer available

Eu acho que utilizar chavetas, sem qualquer "título" para realmente limpar o código e torná-lo mais compreensível.

A única vez que você deve definir uma variável para um valor nulo é quando a variável não sai de escopo e você não precisa mais os dados associados a ela.Caso contrário não é necessário.

Em geral não há necessidade de definir para null.Mas suponha que você tem uma funcionalidade de Redefinição de sua classe.

Em seguida, você pode fazer, porque você não quer chamar dispose duas vezes, pois o Descarte não pode ser implementada corretamente e jogue o Sistema.ObjectDisposed exceção.

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

este tipo de "não há nenhuma necessidade para definir os objetos para null após o uso" não é inteiramente exato.Há momentos em que você precisa para NULL a variável após remover ele.

Sim, você deve SEMPRE chamar .Dispose() ou .Close() em qualquer coisa que tem é quando você está feito.Seja identificadores de arquivos, conexões de banco de dados ou objeto descartável.

Separado do que é a prática padrão de LazyLoad.

Dizem que eu tenho e instanciado ObjA de class A. Class A tem uma propriedade chamada pública PropB de class B.

Internamente, PropB utiliza a variável privada de _B e o padrão é null.Quando PropB.Get() é usado, ele verifica se _PropB é nulo e, se for, abre os recursos necessários para instanciar um B em _PropB.Em seguida, ele retorna _PropB.

A minha experiência, este é realmente um truque útil.

Onde a necessidade de null vem é se você redefinir ou alterar, de alguma forma, que o conteúdo da _PropB foram a criança dos valores anteriores de A, você vai necessitar de deitar fora E nulo fora _PropB assim LazyLoad pode redefinir para obter o valor correto SE o código exige.

Se você só faz _PropB.Dispose() e logo após esperar a verificação de nula para LazyLoad para ter êxito, não será nulo, e você vai estar olhando para dados obsoletos.Em efeito, você deve nulo-lo após Dispose() só para ter certeza.

Eu com certeza gostaria que fosse de outra forma, mas eu tenho o código de agora com este comportamento depois de um Dispose() em um _PropB e fora de chamar a função que fez o Dispose (e, portanto, quase fora do âmbito privado prop ainda não é nulo, e os dados obsoletos ainda está lá.

Eventualmente, o disposto propriedade será nulo, mas que foi não-determinístico do meu ponto de vista.

A razão principal, como dbkk alude é a de que o recipiente pai (ObjA com PropB) é manter a instância do _PropB no âmbito, apesar de o Dispose().

Há alguns casos em que faz sentido para null referências.Por exemplo, quando você está escrevendo uma coleção--como uma fila de prioridade-e pelo seu contrato, você não deve manter os objectos vivos para o cliente depois que o cliente tiver removido da fila.

Mas esse tipo de coisa só é importante na longa duração coleções.Se a fila não vai sobreviver no final da função em que foi criado, em seguida, importa muito menos.

Em um todo, você realmente não deve se preocupar.Permitir que o compilador e o GC de fazer o seu trabalho, então você pode fazer o seu.

Dê uma olhada neste artigo, bem como: http://www.codeproject.com/KB/cs/idisposable.aspx

Para a maior parte, a definição de um objeto nulo não tem efeito.A única vez que você deve ter certeza de fazer isso é se você estiver trabalhando com um grande "objeto", que é maior do que 84K em tamanho (como bitmaps).

Stephen Cleary explica muito bem neste post: Devo Definir Variáveis para Null para Auxiliar a Coleta de Lixo?

Diz:

A Resposta Curta, para o Impaciente Sim, se a variável é um campo estático, ou se você estiver escrevendo um enumerable método (usando yield return) ou um método assíncrono (usando async e await).Caso contrário, não.

Isso significa que, em métodos regulares (não-enumeráveis e não-assíncrono), você não definir variáveis locais, parâmetros de método, ou campos de instância para null.

(Mesmo se você estiver implementando IDisposable.Deite, ainda assim, você não deve definir variáveis para nulo).

A coisa mais importante que devemos considerar é Campos Estáticos.

Campos estáticos são sempre objetos raiz, e , assim, são sempre considerado "vivo" pelo coletor de lixo.Se um campo estático faz referência a um objeto que não é mais necessária, ela deve ser definida para null para que o coletor de lixo irá tratá-lo como elegíveis para a coleção.

Definição de campos estáticos para null não tem sentido se todo o processo está sendo encerrado.Toda a pilha está prestes a ser lixo coletado em que ponto, incluindo todos os objetos raiz.

Conclusão:

Campos estáticos;isso é sobre ele.Qualquer outra coisa é um desperdício de tempo.

Eu acredito que pelo design do GC implementadores, você não pode velocidade de até GC com anulação.Eu tenho certeza que eles preferem que você não preocupe-se com a forma como/quando GC corre-tratá-lo como este onipresente Sendo protegendo e cuidando de e para você...(arcos de cabeça para baixo, levanta o punho para o céu)...

Pessoalmente, eu, muitas vezes, explicitamente definir variáveis para null quando eu sou feito com eles como uma forma de auto-documentação.Eu não declare, use, em seguida, definido como null mais tarde-eu null imediatamente depois que eles deixam de ser necessários.O que estou a dizer, explicitamente, "eu estou oficialmente feito com você...desapareceram..."

Está anulando necessário um GC seria o idioma?Não.É útil para o GC?Talvez sim, talvez não, não sei ao certo, pelo design eu realmente não pode controlar, e independentemente de hoje, a resposta com esta versão, ou que, de futuro GC implementações poderia alterar a resposta fora do meu controle.Além disso, se/quando zeragem é otimizado para fora é pouco mais do que uma fantasia comentário se você vai.

Acho que se ele faz a minha intenção mais clara para a próxima pobre tolo que o segue os meus passos, e se ele "talvez" potencialmente, ajudar a GC, por vezes, então vale a pena para mim.A maioria faz-me sentir limpo e claro, e Mongo gosta de sentir-se limpo e claro.:)

Eu olhar para ele como esta:Linguagens de programação existem para permitir que as pessoas dão outras pessoas uma idéia de intenção e um compilador de uma solicitação de emprego do que fazer -- o compilador converte esse pedido em um idioma diferente (às vezes muitos) para uma CPU -- a CPU(s) poderia dar um pio que o idioma utilizado, o seu guia configurações, comentários, estilística ênfases, os nomes de variáveis, etc.-- uma CPU tudo sobre o fluxo de bits que informa o que registra e opcodes e localizações de memória para twiddle.Muitas coisas escritas em código não se converter no que é consumido pela CPU, na seqüência indicada.Nossa C, C++, C#, Lisp, Babel, montador ou o que é teoria, em vez de realidade, escrito como uma declaração de trabalho.O que você vê não é o que você tem, sim, mesmo que em linguagem assembler.

Eu entendo a mentalidade de "coisas inúteis" (como linhas em branco) "nada mais são que o barulho e a confusão de código." Que foi me mais cedo em minha carreira;Eu totalmente entendo isso.Neste momento, dirijo-me para que o que torna o código mais claro.Não é como eu estou a adição de até 50 linhas de "ruído" para meus programas -- é algumas linhas aqui ou ali.

Há exceções a qualquer regra.Em cenários com a memória volátil, de memória estática, condições de corrida, singletons, de uso de dados "obsoletos" e todo esse tipo de podridão, que é diferente:você PRECISA para gerir a sua própria memória, fecho e anulando como propósito porque a memória não é parte do GC tinha Universo -- espero que todos entendam isso.O resto do tempo com GC gostaria de línguas é uma questão de estilo, em vez de necessidade ou de uma garantia de aumento de desempenho.

No final do dia, certifique-se de que você entende o que é elegível para o GC e o que não é;bloqueio, descarte, e anular de forma adequada;de cera, cera de fora;inspire, expire;e por tudo o mais eu digo:Se ele se sente bem, fazê-lo.Sua milhagem pode variar...como deveria...

Algum objeto suponha que o .dispose() método que força o recurso a ser removida da memória.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top