Pergunta

O destruidor só deve liberar recursos não gerenciados que seu objeto detém sobre a, e não deve fazer referência a outros objetos. Se você só conseguiram referências que você não precisa (e não deve) implementar um destruidor. Você quer que isso só para lidar com recursos não gerenciados. Porque há algum custo para ter um destrutor , você deve implementar isso só em métodos que consomem recursos valiosos, não gerenciados.

- Top Ten Armadilhas em C # para C ++ programadores

O artigo não entrar nessa com mais profundidade, mas que tipos de custos estão envolvidos com o uso de um destruidor em C #?

Nota: Eu sei sobre o GC eo fato do destrutor não é chamado às vezes de confiança, que tudo de lado, é outra coisa lá qualquer coisa

Foi útil?

Solução

Qualquer objecto que tem um finalizador (I preferem esse termo ao longo do processo de destruição, para realçar a diferença a partir de processos de destruição de C ++) é adicionado à fila finalizador. Esta é uma lista de referências a objetos que tem um finalizador que tem de ser chamado antes de serem removidos.

Quando o objeto é para coleta de lixo, a GC vai descobrir que ele é na fila finalizador e mover a referência para a fila freachable (freachable). Esta é a lista que a discussão de fundo finalizador passa por chamar o método finalizador de cada objeto por sua vez.

Uma vez que o finalizador do objeto tem sido chamado, o objeto não está mais na fila finalizador é por isso é apenas um objeto gerenciado regular que o GC pode remover.

Isso tudo significa que, se um objeto tem um finalizador, ele vai sobreviver pelo menos uma coleta de lixo antes que ele possa ser removido. Isso geralmente significa que o objeto será movido para a próxima geração de pilha, que envolve realmente mover os dados na memória de uma pilha para outra.

Outras dicas

A discussão mais extensa tenho visto em como tudo isso funciona foi feito por Joe Duffy . Ele tem mais detalhes do que você possa imaginar.

Depois disso, eu juntos uma abordagem prático para fazer isso em um dia-a-dia -. menos sobre o custo, mas mais sobre a implementação

Guffa e JaredPar cobrir os detalhes muito bem, então eu vou apenas acrescentar uma nota um pouco esotérica sobre finalizadores ou destruidores como a especificação da linguagem C #, infelizmente, chama-los.

Uma coisa a ter em mente é que, desde o segmento finalizador é executado todos os finalizadores em sequência, um impasse em um finalizador irá impedir todas as restantes (e futuro) finalizadores de execução. Uma vez que estes casos não são recolhidos até que seus finalizadores completar um finalizador impasse também irá causar um vazamento de memória.

Este artigo aborda o problema em detalhes. É realmente difícil de resumir numa simples pós SO: http: // MSDN. microsoft.com/en-us/magazine/bb985010.aspx

Guffa resumiu os fatores no custo finalizador muito bem. Houve um sobre o custo de finalizadores em Java que também dá algumas dicas.

Parte do custo em .NET pode ser evitada pela remoção do objecto da fila finalizador com GC.SuppressFinalize. Corri alguns testes rápidos em .net com base no artigo e postou aqui (embora o foco é muito mais do lado de Java).


A seguir é um gráfico dos resultados - ele realmente não têm as melhores marcas ;-). "Debug = true / false" refere-se ao vazio vs finalizador simples:

~ConditionalFinalizer()  
{  
    if (DEBUG)  
    {  
        if (!resourceClosed)  
        {  
            Console.Error.WriteLine("Object not disposed");  
        }  
        resourceClosed = true;  
    }  
} 

"Suprimir = true" refere-se ao facto de GC.SuppressFinalize foi chamado no método dipose.

Resumo

Para .net, remover o objeto da fila finalizador chamando GC.SuppressFinalize é metade do custo de deixar o objeto na fila.

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