¿Cómo disponer una clase en .net?

El recolector de elementos no utilizados de .NET finalmente liberará memoria, pero ¿qué ocurre si desea que la memoria vuelva inmediatamente? ¿Qué código necesita usar en una clase MyClass para llamar?

 MyClass.Dispose() 

y liberar todo el espacio utilizado por variables y objetos en MyClass ?

IDisposable no tiene nada que ver con liberar memoria. IDisposable es un patrón para liberar recursos no administrados , y la memoria es definitivamente un recurso administrado.

Los enlaces que apuntan a GC.Collect () son la respuesta correcta, aunque el uso de esta función generalmente no se recomienda en la documentación de Microsoft .NET.

Editar: Después de haber ganado una cantidad sustancial de karma por esta respuesta, siento cierta responsabilidad de explicarlo, no sea que un recién llegado a la administración de recursos de .NET tenga una impresión equivocada.

Dentro de un proceso .NET, hay dos tipos de recursos gestionados y no gestionados. “Gestionado” significa que el tiempo de ejecución tiene el control del recurso, mientras que “no gestionado” significa que es responsabilidad del progtwigdor. Y realmente solo hay un tipo de recurso administrado que nos importa en .NET hoy: memoria. El progtwigdor le dice al tiempo de ejecución que asigne memoria y luego depende del tiempo de ejecución averiguar cuándo se puede liberar la memoria. El mecanismo que .NET usa para este propósito se llama recolección de basura y puede encontrar mucha información sobre GC en Internet simplemente usando Google.

Para los otros tipos de recursos, .NET no sabe nada sobre cómo limpiarlos, por lo que debe confiar en que el progtwigdor hará lo correcto. Para este fin, la plataforma le da al progtwigdor tres herramientas:

  1. La interfaz IDisposable y la instrucción “using” en VB y C #
  2. Finalizadores
  3. El patrón IDisposable como implementado por muchas clases BCL

El primero de ellos permite que el progtwigdor adquiera de manera eficiente un recurso, lo use y luego lo libere todo dentro del mismo método.

 using (DisposableObject tmp = DisposableObject.AcquireResource()) { // Do something with tmp } // At this point, tmp.Dispose() will automatically have been called // BUT, tmp may still a perfectly valid object that still takes up memory 

Si “AcquireResource” es un método de fábrica que (por ejemplo) abre un archivo y “Dispose” cierra el archivo automáticamente, este código no puede filtrar un recurso de archivo. Pero la memoria para el objeto “tmp” en sí misma todavía puede asignarse. Eso es porque la interfaz IDisposable no tiene absolutamente ninguna conexión con el recolector de basura. Si desea asegurarse de que la memoria se liberó, su única opción sería llamar a GC.Collect() para forzar una recolección de basura.

Sin embargo, no se puede enfatizar lo suficiente que probablemente esta no sea una buena idea. En general, es mucho mejor dejar que el recolector de basura haga lo que está diseñado para hacer, que es administrar la memoria.

¿Qué sucede si el recurso se utiliza durante un período de tiempo más largo, de modo que su vida útil se cruza con varios métodos? Claramente, la statement de “uso” ya no es aplicable, por lo que el progtwigdor tendría que llamar manualmente “Eliminar” cuando haya terminado con el recurso. ¿Y qué sucede si el progtwigdor se olvida? Si no hay una alternativa, entonces el proceso o la computadora pueden eventualmente quedarse sin el recurso que no se libera adecuadamente.

Ahí es donde entran los finalizadores. Un finalizador es un método en su clase que tiene una relación especial con el recolector de basura. El GC promete que, antes de liberar la memoria para cualquier objeto de ese tipo, primero dará al finalizador la oportunidad de realizar algún tipo de limpieza.

Entonces, en el caso de un archivo, teóricamente no necesitamos cerrar el archivo manualmente. Solo podemos esperar hasta que el recolector de basura lo haga y luego dejar que el finalizador haga el trabajo. Desafortunadamente, esto no funciona bien en la práctica porque el recolector de basura funciona de manera no determinista. El archivo puede permanecer abierto considerablemente más tiempo de lo que el progtwigdor espera. Y si se mantienen suficientes archivos abiertos, el sistema puede fallar al intentar abrir un archivo adicional.

Para la mayoría de los recursos, queremos ambas cosas. Queremos que una convención pueda decir “ya hemos terminado con este recurso” y queremos asegurarnos de que haya al menos alguna posibilidad de que la limpieza se realice automáticamente si olvidamos hacerlo manualmente. Ahí es donde el patrón “IDisposable” entra en juego. Esta es una convención que permite IDispose y un finalizador para jugar muy bien juntos. Puede ver cómo funciona el patrón mirando la documentación oficial para IDisposable .

En pocas palabras : si lo que realmente quieres hacer es asegurarte de que la memoria se libera, IDisposable y finalizadores no te ayudarán. Pero la interfaz IDisposable es parte de un patrón extremadamente importante que todos los progtwigdores de .NET deben entender.

Solo puede eliminar instancias que implementen la interfaz IDisposable.

Para forzar una recolección de basura para liberar la memoria (no administrada) de inmediato:

 GC.Collect(); GC.WaitForPendingFinalizers(); 

Esto normalmente es una mala práctica, pero hay, por ejemplo, un error en la versión x64 del framework .NET que hace que el GC se comporte de manera extraña en algunos escenarios, y entonces es posible que desee hacerlo. No sé si el error ya se resolvió. ¿Alguien sabe?

Para eliminar una clase, haz esto:

 instance.Dispose(); 

o así:

 using(MyClass instance = new MyClass()) { // Your cool code. } 

que se traducirá en tiempo de comstackción a:

 MyClass instance = null; try { instance = new MyClass(); // Your cool code. } finally { if(instance != null) instance.Dispose(); } 

Puede implementar la interfaz IDisposable de esta manera:

 public class MyClass : IDisposable { private bool disposed; ///  /// Construction ///  public MyClass() { } ///  /// Destructor ///  ~MyClass() { this.Dispose(false); } ///  /// The dispose method that implements IDisposable. ///  public void Dispose() { this.Dispose(true); GC.SuppressFinalize(this); } ///  /// The virtual dispose method that allows /// classes inherithed from this one to dispose their resources. ///  ///  protected virtual void Dispose(bool disposing) { if (!disposed) { if (disposing) { // Dispose managed resources here. } // Dispose unmanaged resources here. } disposed = true; } } 

Las respuestas a esta pregunta se han confundido un poco.

El título pregunta acerca de la eliminación, pero luego dice que quieren recuperar la memoria de inmediato.

.Net es administrado , lo que significa que cuando escribe aplicaciones .Net no tiene que preocuparse por la memoria directamente, el costo es que tampoco tiene control directo sobre la memoria.

.Net decide cuándo es mejor limpiar y liberar memoria, no usted como el codificador .Net.

The Dispose es una manera de decirle a .Net que ya ha terminado con algo, pero en realidad no liberará la memoria hasta que sea el mejor momento para hacerlo.

Básicamente, .Net recuperará la memoria cuando sea más fácil hacerlo, es muy útil para decidir cuándo. A menos que esté escribiendo algo con mucha memoria, normalmente no necesita anularlo (esta es parte de la razón por la que los juegos no se escriben a menudo en .Net aún; necesitan un control completo).

En .Net puede usar GC.Collect() para forzarlo de inmediato, pero eso casi siempre es una mala práctica. Si .Net aún no lo ha limpiado, eso significa que no es un momento particularmente bueno para hacerlo.

GC.Collect() recoge los objetos que .Net identifica como hechos. Si no ha eliminado un objeto que lo necesita .Net puede decidir mantener ese objeto. Esto significa que GC.Collect() solo es efectivo si implementa correctamente sus instancias desechables.

GC.Collect() no reemplaza el uso correcto de IDisposable.

Por lo tanto, el desecho y la memoria no están relacionados directamente, pero no es necesario que lo sean. La eliminación correcta hará que sus aplicaciones .Net sean más eficientes y, por lo tanto, consumn menos memoria.


99% del tiempo en .Net, la siguiente es la mejor práctica:

Regla 1: si no se ocupa de nada no administrado o que implemente IDisposable entonces no se preocupe por tirar.

Regla 2: si tiene una variable local que implementa IDisposable, asegúrese de deshacerse de ella en el scope actual:

 //using is best practice using( SqlConnection con = new SqlConnection("my con str" ) ) { //do stuff } //this is what 'using' actually compiles to: SqlConnection con = new SqlConnection("my con str" ) ; try { //do stuff } finally { con.Dispose(); } 

Regla 3: si una clase tiene una propiedad o una variable miembro que implementa IDisposable, entonces esa clase también debe implementar IDisposable. En el método Dispose de esa clase también puede deshacerse de sus propiedades IDisposable:

 //rather basic example public sealed MyClass : IDisposable { //this connection is disposable public SqlConnection MyConnection { get; set; } //make sure this gets rid of it too public Dispose() { //if we still have a connection dispose it if( MyConnection != null ) MyConnection.Dispose(); //note that the connection might have already been disposed //always write disposals so that they can be called again } } 

Esto no está completo, por lo que el ejemplo está sellado. Heredar clases puede necesitar observar la siguiente regla …

Regla 4: si una clase usa un recurso no administrado , implemente IDispose y agregue un finalizador.

.Net no puede hacer nada con el recurso no administrado , por lo que ahora estamos hablando de memoria. Si no lo limpia, puede tener una pérdida de memoria.

El método Dispose necesita tratar con recursos administrados y no administrados .

El finalizador es un seguro: garantiza que si otra persona crea una instancia de su clase y no lo elimina, los recursos no administrados “peligrosos” aún pueden ser limpiados por .Net.

 ~MyClass() { //calls a protected method //the false tells this method //not to bother with managed //resources this.Dispose(false); } public void Dispose() { //calls the same method //passed true to tell it to //clean up managed and unmanaged this.Dispose(true); //as dispose has been correctly //called we don't need the //'backup' finaliser GC.SuppressFinalize(this); } 

Finalmente esta sobrecarga de Dispose que toma una bandera booleana:

 protected virtual void Dispose(bool disposing) { //check this hasn't been called already //remember that Dispose can be called again if (!disposed) { //this is passed true in the regular Dispose if (disposing) { // Dispose managed resources here. } //both regular Dispose and the finaliser //will hit this code // Dispose unmanaged resources here. } disposed = true; } 

Tenga en cuenta que una vez que todo esté en su lugar, otro código administrado que cree una instancia de su clase puede tratarlo como cualquier otro IDisposable (Reglas 2 y 3).

¿Sería apropiado mencionar también que disponer no siempre se refiere a la memoria? Dispongo recursos como referencias a archivos con más frecuencia que la memoria. GC.Collect () se relaciona directamente con el recolector de basura CLR y puede o no liberar memoria (en el Administrador de tareas). Es probable que afecte su aplicación de forma negativa (por ejemplo, rendimiento).

Al final del día, ¿por qué quieres recuperar la memoria inmediatamente? Si hay presión de memoria de otra parte, el sistema operativo obtendrá memoria en la mayoría de los casos.

Eche un vistazo a este artículo

Implementar el patrón Dispose, IDisposable y / o un finalizador no tiene absolutamente nada que ver con la recuperación de la memoria; en cambio, tiene todo que ver con decirle al CG cómo reclamar esa memoria. Cuando llamas a Dispose (), de ninguna manera estás interactuando con el GC.

El GC solo se ejecutará cuando determine la necesidad (llamada presión de memoria) y luego (y solo entonces) desasignará la memoria para los objetos no utilizados y compactará el espacio de la memoria.

Podrías llamar a GC.Collect () pero no deberías hacerlo a menos que haya una buena razón para hacerlo (que casi siempre es “Never”). Cuando fuerza un ciclo de recolección fuera de banda como este, en realidad hace que el GC haga más trabajo y finalmente puede dañar el rendimiento de sus aplicaciones. Durante la duración del ciclo de recolección de GC, su aplicación se encuentra en estado congelado … cuantos más ciclos de GC se ejecuten, más tiempo se congelará su aplicación.

También hay algunas llamadas a la API Win32 nativas que puede hacer para liberar su conjunto de trabajo, pero incluso esas deben evitarse a menos que haya una muy buena razón para hacerlo.

Toda la premisa detrás de un tiempo de ejecución recolectado de gargbage es que no necesita preocuparse (tanto) sobre cuándo el tiempo de ejecución asigna / desasigna memoria real; solo tiene que preocuparse de asegurarse de que su objeto sepa cómo limpiarlo después cuando se lo solicite.

 public class MyClass : IDisposable { public void Dispose() { // cleanup here } } 

entonces puedes hacer algo como esto

 MyClass todispose = new MyClass(); todispose.Dispose(); // instance is disposed right here 

o

 using (MyClass instance = new MyClass()) { } // instance will be disposed right here as it goes out of scope 

Explicación completa de Joe Duffy sobre ” Disposición, finalización y gestión de recursos “:

Anteriormente, en la vida útil de .NET Framework, los progtwigdores de C # se referían sistemáticamente a los finalizadores como destructores. A medida que nos volvemos más inteligentes con el tiempo, estamos tratando de aceptar el hecho de que el método Dispose es realmente más equivalente a un destructor de C ++ (determinístico) , mientras que el finalizador es algo completamente independiente (no determinista) . El hecho de que C # tomó prestada la syntax del destructor de C ++ (es decir, ~ T ()) seguramente tuvo al menos algo que ver con el desarrollo de este nombre inapropiado.

Escribí un resumen de Destructors and Dispose and Garbage collection en http://codingcraftsman.wordpress.com/2012/04/25/to-dispose-or-not-to-dispose/

Para responder la pregunta original:

  1. No trates de administrar tu memoria
  2. Dispose no se trata de gestión de memoria, se trata de gestión de recursos no gestionados
  3. Los finalizadores son una parte innata del patrón Dispose y en realidad ralentizan la liberación de memoria de los objetos administrados (ya que tienen que ir a la cola de Finalización a menos que ya estén desechados d)
  4. GC.Collect es malo, ya que hace que algunos objetos de corta duración parezcan necesarios por más tiempo y, por lo tanto, los ralentiza para no ser recostackdos.

Sin embargo, GC.Collect podría ser útil si tuvieras una sección crítica del rendimiento del código y quisieras reducir la probabilidad de que Garbage Collection lo desacelere. Llamas eso antes.

Además de eso, hay un argumento a favor de este patrón:

 var myBigObject = new MyBigObject(1); // something happens myBigObject = new MyBigObject(2); // at the above line, there are temporarily two big objects in memory and neither can be collected 

vs

 myBigObject = null; // so it could now be collected myBigObject = new MyBigObject(2); 

¡Pero la respuesta principal es que Garbage Collection simplemente funciona a menos que lo arruines!

Realmente no se puede obligar a un GC a limpiar un objeto cuando lo desee, aunque hay formas de forzarlo a funcionar, nada dice que se limpie todo el objeto que se desea. Lo mejor es llamar a dispose en un try catch ex finalmente deshacerse de try try (VB.NET rulz) way. Pero Dispose es para limpiar los recursos del sistema (memoria, identificadores, conexiones db, etc.) asignados por el objeto de forma determinista. Dispose no limpia (y no puede) la memoria utilizada por el objeto en sí, solo el GC puedo hacer eso.

Este artículo tiene una guía bastante sencilla. Sin embargo, tener que llamar al GC en lugar de dejar que siga su curso natural es en general un signo de mala gestión de diseño / memoria, especialmente si no se consumen recursos limitados (conexiones, identificadores, cualquier otra cosa que normalmente lleve a implementar IDisposable).

¿Qué está causando que necesites hacer esto?

La interfaz IDisposable es realmente para clases que contienen recursos no administrados. Si su clase no contiene recursos no administrados, ¿por qué necesita liberar recursos antes de que lo haga el recolector de elementos no utilizados? De lo contrario, solo asegúrese de que su objeto se instancia lo más tarde posible y se sale del scope lo antes posible.

Lo siento, pero la respuesta seleccionada aquí es incorrecta. Como algunas personas han declarado posteriormente, tirar e implementar IDisposable no tiene nada que ver con liberar la memoria asociada con una clase .NET. Se utiliza principal y tradicionalmente para liberar recursos no administrados, como manejadores de archivos, etc.

Si bien su aplicación puede llamar a GC.Collect () para intentar forzar una recostackción por parte del recolector de elementos no utilizados, esto solo tendrá un efecto real en los elementos que están en el nivel de generación correcto en la cola localizable. Por lo tanto, es posible que si ha borrado todas las referencias al objeto, aún pueda haber un par de llamadas a GC.Collect () antes de que se libere la memoria real.

No dice en su pregunta POR QUÉ siente la necesidad de liberar memoria de inmediato. Entiendo que a veces puede haber circunstancias inusuales, pero en serio, en el código administrado casi siempre es mejor dejar que el tiempo de ejecución se ocupe de la administración de la memoria.

Probablemente el mejor consejo si piensa que su código está consumiendo memoria más rápido de lo que el GC lo está liberando, entonces debe revisar su código para asegurarse de que no se haga referencia a ningún objeto que ya no necesite en ninguna estructura de datos que tenga en miembros estáticos, etc. También trate de evitar situaciones donde tenga referencias circulares de objetos, ya que es posible que tampoco se liberen.

@Keith,

Estoy de acuerdo con todas tus reglas excepto la # 4. Agregar un finalizador solo debe hacerse bajo circunstancias muy específicas. Si una clase utiliza recursos no administrados, estos deben limpiarse en su función Dispose (bool). Esta misma función solo debe limpiar los recursos administrados cuando bool es verdadero. Agregar un finalizador agrega un costo de complejidad al uso de su objeto ya que cada vez que crea una nueva instancia también debe colocarse en la cola de finalización, que se verifica cada vez que el GC ejecuta un ciclo de recostackción. Efectivamente, esto significa que su objeto sobrevive un ciclo / generación más de lo que debería para poder ejecutar el finalizador. El finalizador no debe considerarse como una “red de seguridad”.

El GC solo ejecutará un ciclo de recostackción cuando determine que no hay suficiente memoria disponible en el montón Gen0 para realizar la siguiente asignación, a menos que la “ayude” llamando a GC.Collect () para forzar una colección fuera de banda. .

La conclusión es que, pase lo que pase, el GC solo sabe cómo liberar recursos llamando al método Dispose (y posiblemente al finalizador si se implementa). Depende de ese método “hacer lo correcto” y limpiar todos los recursos no administrados utilizados e indicar a cualquier otro recurso gestionado que llame a su método Dispose. Es muy eficiente en lo que hace y puede auto optimizarse en gran medida siempre que no sea ayudado por los ciclos de recolección fuera de banda. Dicho esto, a menos que se llame a GC. Recoja explícitamente que no tiene control sobre cuándo y en qué orden se eliminarán los objetos y se liberará la memoria.

Si no desea (o no puede) implementar IDisposable en su clase, puede forzar la recolección de basura de esta manera (pero es lenta) –

 GC.Collect(); 

Puede tener destrucción de objeto determinista en c ++

Nunca desea llamar a GC.Collect, se confunde con el autoajuste del recolector de basura para detectar la presión de memoria y en algunos casos no hace nada más que boost la generación actual de cada objeto en el montón.

Para aquellos que publican respuestas IDisposable. Llamar a un método Dispose no destruye un objeto como lo describe el asker.

@Keith:

IDisposable es para recursos administrados.

Los finalizadores son para recursos no administrados.

Lo siento, pero eso está mal. Normalmente, el finalizador no hace nada en absoluto. Sin embargo, si el patrón de disposición ha sido implementado correctamente, el finalizador intenta invocar Dispose .

Dispose tiene dos trabajos:

  • Recursos no administrados gratuitos, y
  • recursos gestionados nesteds gratuitos.

Y aquí entra en juego su afirmación porque es cierto que, al finalizar, un objeto nunca debe tratar de liberar recursos administrados nesteds, ya que estos ya pueden haberse liberado. Sin embargo, aún debe liberar recursos no administrados.

Aún así, los finalizadores no tienen otro trabajo que llamar a Dispose y decirle que no toque objetos administrados. Dispose , cuando se lo llame manualmente (o mediante el Using ), liberará todos los recursos no administrados y pasará el mensaje Dispose a objetos nesteds (y métodos de clase base) pero esto nunca liberará ninguna memoria (administrada).

Konrad Rudolph – sí, normalmente el finalizador no hace nada en absoluto. No debes implementarlo a menos que estés tratando con recursos no administrados.

Luego, cuando lo implemente, use el patrón de disposición de Microsoft (como ya se describió)

  • public Dispose() llamadas protected Dispose(true) : trata con recursos administrados y no administrados. Calling Dispose() debe suprimir la finalización.

  • ~Finalize calls protected Dispose(false) : solo trata con recursos no administrados. Esto evita memory leaks no administradas si no llama al public Dispose()

~Finalize es lento y no debe usarse a menos que tenga recursos no administrados para tratar.

Los recursos administrados no pueden perder memoria, solo pueden desperdiciar recursos para la aplicación actual y ralentizar su recolección de basura. Los recursos no administrados pueden tener fugas y ~Finalize es la mejor práctica para garantizar que no lo hagan.

En cualquier caso, using es la mejor práctica.

@Curt Hagenlocher – eso está de vuelta al frente. No tengo idea de por qué tantos lo han votado cuando está mal.

IDisposable es para recursos administrados .

Los finalizadores son para recursos no administrados .

Siempre y cuando solo use recursos administrados tanto @Jon Limjap como yo mismo somos enteramente correctos.

Para las clases que usan recursos no administrados (y tenga en cuenta que la gran mayoría de las clases de .Net no) la respuesta de Patrik es completa y la mejor práctica.

Evite utilizar GC.Collect: es una forma lenta de tratar con los recursos administrados, y no hace nada con los no administrados a menos que haya creado correctamente sus ~ Finalizers.


Eliminé el comentario del moderador de la pregunta original en línea con https://stackoverflow.com/questions/14593/etiquette-for-modifying-posts

En respuesta a la pregunta original, con la información dada hasta ahora por el póster original, es 100% seguro de que no sabe lo suficiente sobre la progtwigción en .NET como para recibir la respuesta: use GC.Collect (). Diría que es 99.99% probable que realmente no necesite usar GC.Collect () en absoluto, como la mayoría de los carteles han señalado.

La respuesta correcta se reduce a ‘Deje que el GC haga su trabajo. Período. Tienes otras cosas de qué preocuparte. Pero es posible que desee considerar si debe deshacerse de objetos específicos o eliminarlos, y si necesita implementar IDisposable y posiblemente finalizar en su clase.

En cuanto a la publicación de Keith y su Regla # 4:

Algunos carteles confunden la regla 3 y la regla 4. La regla 4 de Keith es absolutamente correcta, inequívoca. Es la única regla de las cuatro que no necesita edición. Reformularía ligeramente algunas de sus otras reglas para hacerlas más claras, pero son esencialmente correctas si las analiza correctamente, y realmente lee la publicación completa para ver cómo se expande sobre ellas.

  1. Si su clase no utiliza un recurso no administrado Y tampoco crea nunca otro objeto de una clase que use, directamente o en última instancia, un objeto no administrado (es decir, una clase que implementa IDisposable), entonces no habría necesidad de su clase ya sea para implementar IDisposable en sí mismo, o incluso para invocar .disponer en cualquier cosa. (En tal caso, es tonto pensar que en realidad NECESITAS liberar inmediatamente la memoria con un GC forzado).

  2. Si su clase utiliza un recurso no administrado, O crea una instancia de otro objeto que implementa IDisposable, entonces su clase debe:

    a) deseche / libere estos inmediatamente en un contexto local en el cual fueron creados, O …

    b) implemente IDisposable en el patrón recomendado dentro de la publicación de Keith, o en algunos miles de sitios en Internet, o en literalmente alrededor de 300 libros por ahora.

    b.1) Además, si (b), y es un recurso no gestionado que ha sido abierto, tanto IDisposable como FINALIZADO SIEMPRE DEBERÍAN implementarse, de acuerdo con la Regla # 4 de Keith.
    En este contexto, Finalize absolutamente ES una red de seguridad en un sentido: si alguien ejemplifica SU objeto IDisposable que usa un recurso no administrado, y no puede invocar a disponer, entonces Finalize es la última oportunidad para que SU objeto cierre correctamente el recurso no administrado.
    (Finalize debe hacer esto llamando a Dispose de tal forma que el método Dispose omita la liberación de cualquier cosa PERO el recurso no administrado. Alternativamente, si el método Dispose de su objeto se llama adecuadamente por cualquier instancia de su objeto, AMBOS pasa la llamada Dispose a todos los objetos identificables que ha instanciado, Y libera los recursos no administrados correctamente, terminando con una llamada para suprimir la Finalización en su objeto, lo que significa que el impacto del uso de Finalizar se reduce si la persona que llama ordena correctamente su objeto. Todos estos puntos están incluidos en la publicación de Keith, BTW.)

    b.2) Si su clase solo está implementando IDisposable porque necesita esencialmente pasar un Dispose a un objeto IDisposable que ha instanciado, entonces no implemente un método Finalize en su clase en ese caso. Finalize es para manejar el caso de que TANTO desecho nunca fue invocado por cualquier instancia de su objeto, Y se utilizó un recurso no administrado que aún no se lanzó.

En resumen, con respecto a la publicación de Keith, él es completamente correcto, y esa publicación es la respuesta más correcta y completa, en mi opinión. Puede usar algunas afirmaciones breves que algunos encuentran “incorrectas” u objetar, pero su publicación completa se expande completamente sobre el uso de Finalize, y está absolutamente en lo correcto. Asegúrese de leer su publicación por completo antes de saltar sobre una de las reglas o declaraciones preliminares en su publicación.

Si MyClass implementa IDisposable, puede hacer eso.

 MyClass.Dispose(); 

La mejor práctica en C # es:

 using( MyClass x = new MyClass() ) { //do stuff } 

Como eso termina el desecho en un bash finalmente y se asegura de que nunca se pierda.