2011-02-04 26 views
146

Por ejemplo:¿Cuándo debería crear un destructor?

public class Person 
{ 
    public Person() 
    { 
    } 

    ~Person() 
    { 
    } 
} 

Cuando debería crear manualmente un destructor? ¿Cuándo necesitó crear un destructor?

+5

Se llama DESTRUCTOR- no "con" en ella. en C#, como no puedes deconstruir objetos, se llama FINALIZER. – TomTom

+3

Suena más metal. Gracias por aclarar eso. :) –

+4

Cuando te sientes imprudente. – capdragon

Respuesta

64

El lenguaje C# llama a estos "destructores", pero la mayoría de las personas los llaman "finalizadores" ya que ese es su nombre .NET y reduce la confusión con los destructores C++ (que son bastante diferentes).

How to Implement IDisposable and Finalizers: 3 Easy Rules

+4

Aquí hay un enlace actualizado en caso de que la redirección muera http://blog.stephencleary.com/2009/08/how-to-implement-disposable-and.html – JSoet

+3

Esto no parece abordar la pregunta principal de "** cuando ** para crear un destructor". – ANeves

3

Se llama destructor/finalizador, y generalmente se crea cuando se implementa el patrón Dispuesto.

Es una solución alternativa cuando el usuario de su clase olvida llamar a Dispose, para asegurarse de que (eventualmente) sus recursos se liberen, pero no tiene ninguna garantía en cuanto a cuándo se llama al destructor.

En este Stack Overflow question, la respuesta aceptada muestra correctamente cómo implementar el patrón de eliminación. Esto solo es necesario si su clase contiene recursos no modificados que el recolector de basura no puede limpiar por sí mismo.

Una buena práctica es no implementar un finalizador sin dar también al usuario de la clase la posibilidad de deshacerse del objeto manualmente para liberar los recursos de inmediato.

+0

En realidad NO se llama destructor en C# por una buena razón. – TomTom

+13

En realidad ** es **. Gracias por darme un voto negativo porque estás equivocado. Consulte la biblioteca de MSDN con respecto a este problema específico: http://msdn.microsoft.com/en-us/library/66x5fx1b.aspx –

+1

@TomTom su nombre oficial es destructor –

8

No necesita uno a menos que su clase mantenga recursos no administrados como los identificadores de archivos de Windows.

+5

Bueno, en realidad, se llama destructor –

+2

Ahora estoy confundido. ¿Es finalizador o destructor? –

+4

La especificación C# lo llama de hecho un destructor. Algunos ven esto como un error. http://stackoverflow.com/questions/1872700/the-difference-between-a-destructor-and-a-finalizer – Ani

3

cuando se tienen recursos no administrados y hay que asegurarse de que se limpiarán cuando el objeto desaparece. Un buen ejemplo serían los objetos COM o File Handlers.

14

Se denomina "finalizador", y normalmente solo debe crear uno para una clase cuyo estado (es decir, campos) incluya recursos no administrados (es decir, punteros a identificadores recuperados mediante llamadas p/invoke). Sin embargo, en .NET 2.0 y posterior, en realidad hay una mejor manera de lidiar con la limpieza de recursos no administrados: SafeHandle. Teniendo esto en cuenta, prácticamente nunca deberás escribir un finalizador de nuevo.

+6

-1: No se llama Finalizador. –

+20

@ThomasEding - [Sí lo es] (http://msdn.microsoft.com/en-us/library/0s71x931 (v = vs.80) .aspx). C# usa la sintaxis de destructor, pero en realidad está creando un [finalizador] (http://en.wikipedia.org/wiki/Finalizer). [Nuevamente] (http://msdn.microsoft.com/en-us/library/66x5fx1b.aspx). – JDB

0

Destructors proporcionan una forma implícita de liberar recursos no administrados encapsulados en su clase, se llaman cuando el GC se acerca e implícitamente llaman al método Finalize de la clase base. Si está utilizando muchos recursos no administrados, es mejor proporcionar una forma explícita de liberar esos recursos a través de la interfaz IDisposable. Consulte la guía de programación de C#: http://msdn.microsoft.com/en-us/library/66x5fx1b.aspx

187

ACTUALIZACIÓN: Esta pregunta fue the subject of my blog in May of 2015. Gracias por la gran pregunta! Vea en el blog una larga lista de falsedades que las personas comúnmente creen acerca de la finalización.

¿Cuándo debería crear manualmente un destructor?

Casi nunca.

Normalmente, uno solo crea un destructor cuando su clase se aferra a algún recurso caro no administrado que debe limpiarse cuando el objeto desaparece. Es mejor usar el patrón desechable para garantizar que el recurso se limpie. Un destructor es, en esencia, una garantía de que si el consumidor de su objeto se olvida de eliminarlo, el recurso todavía se limpia con el tiempo. (Tal vez.)

Si comete un destructor ser extremadamente cuidadoso y entender cómo funciona el recolector de basura. Los destructores son realmente extraño :

  • Ellos no se ejecutan en el hilo; corren en su propio hilo. ¡No provoques estancamientos!
  • Una excepción no controlada lanzada desde un destructor es una mala noticia. Está en su propio hilo; ¿Quién lo va a atrapar?
  • Se puede invocar un destructor en un objeto después de el constructor se inicia pero antes de termina el constructor. Un destructor escrito correctamente no se basará en los invariantes establecidos en el constructor.
  • Un destructor puede "resucitar" un objeto, haciendo que un objeto muerto vuelva a estar vivo. Eso es realmente extraño. No lo hagas
  • Es posible que nunca se ejecute un destructor; no puede confiar en que el objeto se haya programado para su finalización. Es probablemente será, pero eso no es una garantía.

Casi nada que sea cierto normalmente es cierto en un destructor. Sé realmente, muy cuidadoso. Escribir un destructor correcto es muy difícil.

¿Cuándo necesitó crear un destructor?

Al probar la parte del compilador que maneja los destructores. Nunca tuve que hacerlo en el código de producción. Casi nunca escribo objetos que manipulen recursos no administrados.

+0

"Se puede invocar a un destructor sobre un objeto después de que se inicie el constructor, pero antes de que el constructor finalice". Pero puedo confiar en que los inicializadores de campo se han ejecutado, ¿verdad? – configurator

+10

@configurator: No. Supongamos que el tercer inicializador de campo de un objeto con un finalizador llamó un método estático que provocó que se lanzara una excepción. ¿Cuándo se ejecutará el cuarto inicializador de campo? Nunca. Pero el objeto todavía está asignado y debe estar finalizado. Diablos, ni siquiera tienes una garantía de que los campos de tipo double se inicializaron * completamente * cuando se ejecuta el dtor. Pudo haber habido un aborto de hilo a la mitad de escribir el doble y ahora el finalizador tiene que lidiar con un doble medio inicializado a medias. –

+1

Publicación excelente, pero debería haber dicho "debe crearse cuando su clase se aferra a algún objeto caro no administrado o hace que existan grandes cantidades de objetos no administrados" - Para un ejemplo concreto, tengo una clase de matriz en C# que utiliza un nativo subyacente Clase de matriz C++ para hacer un montón de trabajo pesado - Hago muchas matrices - un "destructor" es muy superior a IDisposable en este caso específico, porque mantiene los lados administrados y no administrados de la casa en mejor sincronización –

2

He utilizado un destructor (solo para fines de depuración) para ver si un objeto se estaba eliminando de la memoria en el ámbito de una aplicación WPF. No estaba seguro de si la recolección de basura realmente estaba purgando el objeto de la memoria, y esta era una buena forma de verificarlo.

Cuestiones relacionadas