Quando devo criar um destruidor?

Por exemplo:

public class Person { public Person() { } ~Person() { } } 

Quando devo criar manualmente um destruidor? Quando você precisou criar um destruidor?

    A linguagem C # chama esses “destruidores”, mas a maioria das pessoas os chama de “finalizadores”, já que é o nome .NET deles e reduz a confusão com os destruidores de C ++ (que são bem diferentes).

    Como implementar IDisposable e finalizadores: 3 regras fáceis

    ATUALIZAÇÃO: Esta questão foi o tema do meu blog em maio de 2015 . Obrigado pela ótima pergunta! Veja no blog uma longa lista de falsidades que as pessoas geralmente acreditam na finalização.

    Quando devo criar manualmente um destruidor?

    Quase nunca.

    Normalmente, um só cria um destrutor quando sua class está mantendo algum recurso não gerenciado caro que deve ser limpo quando o object desaparece. É melhor usar o padrão descartável para garantir que o recurso seja limpo. Um destruidor é, então, essencialmente uma garantia de que, se o consumidor do seu object esquecer de descartá-lo, o recurso ainda será limpo eventualmente. (Talvez.)

    Se você fizer um destruidor, seja extremamente cuidadoso e entenda como o coletor de lixo funciona . Destrutores são realmente estranhos :

    • Eles não correm no seu fio; eles correm em seu próprio segmento. Não cause deadlocks!
    • Uma exceção não tratada lançada de um destruidor é uma má notícia. Está no seu próprio segmento; quem vai pegá-lo?
    • Um destruidor pode ser chamado em um object depois que o construtor for iniciado, mas antes do construtor terminar. Um destruidor escrito corretamente não vai depender de invariantes estabelecidos no construtor.
    • Um destruidor pode “ressuscitar” um object, tornando vivo um object morto novamente. Isso é muito estranho. Não faça isso.
    • Um destruidor pode nunca ser executado; você não pode confiar no object que está sendo agendado para finalização. Provavelmente será, mas isso não é garantia.

    Quase nada que normalmente é verdade é verdade em um destruidor. Seja muito, muito cuidadoso. Escrever um destruidor correto é muito difícil.

    Quando você precisou criar um destruidor?

    Ao testar a parte do compilador que lida com destruidores. Eu nunca precisei fazer isso no código de produção. Eu raramente escrevo objects que manipulam resources não gerenciados.

    É chamado de “finalizador”, e normalmente você deve criar apenas um para uma class cujo estado (isto é: campos) inclua resources não gerenciados (isto é: pointers para manipuladores recuperados via chamadas p / invoke). No entanto, no .NET 2.0 e posterior, há realmente uma maneira melhor de lidar com a limpeza de resources não gerenciados: o SafeHandle . Considerando isso, você praticamente nunca precisará escrever um finalizador novamente.

    Você não precisa de um, a menos que sua class mantenha resources não gerenciados, como identificadores de arquivos do Windows.

    É chamado de destruidor / finalizador e geralmente é criado ao implementar o padrão Disposto.

    É uma solução de fallback quando o usuário da sua class esquece de chamar Dispose, para ter certeza de que (eventualmente) seus resources são liberados, mas você não tem garantia de quando o destruidor é chamado.

    Nesta pergunta sobre estouro de pilha , a resposta aceita mostra corretamente como implementar o padrão de descarte. Isso é necessário apenas se a sua class contiver resources não distribuídos que o coletor de lixo não consiga limpar sozinho.

    Uma boa prática é não implementar um finalizador sem também dar ao usuário da class a possibilidade de descartar manualmente o object para liberar os resources imediatamente.

    Quando você tem resources não gerenciados e precisa ter certeza de que eles serão limpos quando seu object for embora. Bom exemplo seria objects COM ou manipuladores de arquivos.

    Eu usei um destrutor (apenas para fins de debugging) para ver se um object estava sendo removido da memory no escopo de um aplicativo WPF. Eu não tinha certeza se a garbage collection estava realmente removendo o object da memory, e essa era uma boa maneira de verificar.

    Os destruidores fornecem uma maneira implícita de liberar resources não gerenciados encapsulados em sua class, eles são chamados quando o GC se aproximar dele e implicitamente chamam o método Finalize da class base. Se você estiver usando muitos resources não gerenciados, é melhor fornecer uma maneira explícita de liberar esses resources por meio da interface IDisposable. Veja o guia de programação C #: http://msdn.microsoft.com/pt-br/library/66x5fx1b.aspx