Cómo deshacerse de una clase in.net?


El recolector de basura. NET eventualmente liberará memoria, pero ¿qué pasa si desea que la memoria vuelva de inmediato? ¿Qué código necesita usar en una clase MyClass para llamar a

MyClass.Dispose()

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

Author: Jon Galloway, 2008-08-15

20 answers

IDesposable no tiene nada que ver con liberar memoria. IDesposable es un patrón para liberar recursos no administrados and 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 es generalmente desaconsejado por la documentación de Microsoft. NET.

Editar: Habiendo ganado una cantidad sustancial de karma por esta respuesta, siento una cierta responsabilidad de desarrollarla, para que un recién llegado para. NET administración de recursos obtener la impresión equivocada.

Dentro de un proceso.NET, hay dos tipos de recursos managed administrados y no administrados. "Administrado "significa que el tiempo de ejecución está en control del recurso, mientras que" no administrado " significa que es responsabilidad del programador. Y realmente solo hay un tipo de recurso administrado que nos importa en. NET hoy en día memory la memoria . El programador le dice al tiempo de ejecución que asigne memoria y después de eso depende del tiempo de ejecución para averiguar cuándo la memoria puede liberarse. El mecanismo que. NET utiliza 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 limpiarlos, por lo que tiene que confiar en que el programador haga lo correcto. Con este fin, la plataforma le da al programador tres herramientas:

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

El primero de estos permite al programador adquirir eficientemente un recurso, usarlo y luego liberarlo 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 automáticamente el archivo, entonces este código no puede filtrar un recurso de archivo. Pero la memoria para el objeto" tmp " en sí puede ser asignar. Esto se debe a que la interfaz identificable 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 aGC.Collect() para forzar una recolección de basura.

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

¿Qué sucede si el recurso está siendo utilizado por un período de tiempo más largo, de tal manera que su vida útil cruza varios métodos? Claramente, la instrucción " using "ya no es aplicable, por lo que el programador tendría que llamar manualmente a" Dispose " cuando haya terminado con el recurso. ¿Y qué pasa si el programador se olvida? Si no hay respaldo, entonces el proceso o la computadora eventualmente se quedarán sin el recurso que no esté siendo liberado correctamente.

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 before antes de liberar la memoria para cualquier objeto de ese tipo first primero le dará al finalizador la oportunidad de hacer algún tipo de limpieza.

Así que en el caso de un archivo, teóricamente no necesitamos cerrar el archivo manualmente. Podemos esperar hasta que el recolector de basura llegue a él y luego dejar que el finalizador haga el trabajo. Desafortunadamente, esto no funciona bien en la práctica porque el recolector de basura funciona no determinista. El archivo puede permanecer abierto considerablemente más tiempo de lo que el programador espera. Y si se mantienen abiertos suficientes archivos, 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 sea capaz de decir "hemos terminado con este recurso ahora" y queremos asegurarnos de que hay al menos alguna posibilidad de que la limpieza ocurra automáticamente si olvidamos hacerlo manualmente. Ahí es donde el "IDisposable" el patrón entra en juego. Esta es una convención que permite IDispose y un finalizer para jugar muy bien juntos. Puede ver cómo funciona el patrón mirando la documentación oficial para visualizable.

Línea de base: Si lo que realmente quieres hacer es asegurarse de que la memoria se libera, entonces IDisposable y finalizadores no le ayudará. Pero la interfaz identificable es parte de un patrón extremadamente importante que todos los programadores de.NET deben entender.

 100
Author: Curt Hagenlocher,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-02 01:44:45

Solo se pueden eliminar instancias que implementen la interfaz identificable.

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

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

Esto normalmente es una mala práctica, pero hay, por ejemplo, un error en la versión x64 de.NET framework que hace que el GC se comporte extraño en algunos escenarios, y entonces es posible que desee hacer esto. No se si el bug ha sido resuelto todavía. ¿Alguien lo sabe?

Para disponer de una clase que haces esto:

instance.Dispose();

O así:

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

Que se traducirá en tiempo de compilación a:

MyClass instance = null;    

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

Puede implementar la interfaz identificable de la siguiente manera:

public class MyClass : IDisposable
{
    private bool disposed;

    /// <summary>
    /// Construction
    /// </summary>
    public MyClass()
    {
    }

    /// <summary>
    /// Destructor
    /// </summary>
    ~MyClass()
    {
        this.Dispose(false);
    }

    /// <summary>
    /// The dispose method that implements IDisposable.
    /// </summary>
    public void Dispose()
    {
        this.Dispose(true);
        GC.SuppressFinalize(this);
    }

    /// <summary>
    /// The virtual dispose method that allows
    /// classes inherithed from this one to dispose their resources.
    /// </summary>
    /// <param name="disposing"></param>
    protected virtual void Dispose(bool disposing)
    {
        if (!disposed)
        {
            if (disposing)
            {
                // Dispose managed resources here.
            }

            // Dispose unmanaged resources here.
        }

        disposed = true;
    }
}
 22
Author: Patrik Svensson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-26 09:31:11

Las respuestas a esta pregunta tiene más que un poco confundido.

El título pregunta sobre la eliminación, pero luego dice que quieren recuperar la memoria inmediatamente.

. Net es administrado, lo que significa que cuando escribe aplicaciones. Net no necesita preocuparse directamente por la memoria, 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 de. Net.

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

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

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

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

GC.Collect() es no un reemplazo para usar correctamente Imposible.

Así que Disponer y la memoria no están directamente relacionados, pero no necesitan estarlo. Desechar correctamente hará que sus aplicaciones. Net sean más eficientes y, por lo tanto, usen menos memoria.


El 99% de las veces en. Net lo siguiente es una buena práctica:

Regla 1: Si no tratas con nada no administrado o que implemente IDisposable entonces no te preocupes por Disponer.

Regla 2: Si tiene una variable local que implementa Visualizable asegúrese de deshacerse de él en el ámbito 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 variable miembro que implementa identificable, entonces esa clase debe implementar Identificable también. En el método de Eliminación de esa clase también puede deshacerse de sus propiedades identificables:

//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á realmente completo, por lo que el ejemplo está sellado. Las clases heredadas pueden necesitar observar la siguiente regla...

Regla 4: Si una clase usa un recurso no administrado luego implementa IDispose y agrega un finalizador.

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

El método de Eliminación debe tratar con recursos administrados y no administrados.

El finalizador es una trampa de seguridad-se asegura de que si alguien más crea e instancia de su clase y falla para eliminarlo, los recursos' peligrosos ' no administrados 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 Disponer 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 esto esté en su lugar, otro código administrado que cree una instancia de su clase puede tratarla como cualquier otro identificable (Reglas 2 y 3).

 18
Author: Keith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-01 09:09:20

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

Al final del día ¿por qué quieres que te devuelva la memoria inmediatamente? Si hay presión de memoria desde otro lugar, el sistema operativo le proporcionará memoria la mayoría de los casos.

 14
Author: Brian Lyttle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-15 15:41:02

Echa un vistazo a este artículo

Implementar el patrón Dispose, IDesposable, y / o un finalizador no tiene absolutamente nada que ver con cuando la memoria se recupera; en su lugar, tiene todo que ver con decirle al GC cómo para recuperar ese recuerdo. 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 entonces (y solo entonces) desasignará memoria para objetos no utilizados y compactar el espacio de memoria.

Usted podría llamar a GC.Collect() pero realmente no deberías a menos que haya una muy buena razón para hacerlo (que casi siempre es "Nunca"). Cuando fuerza un ciclo de recolección fuera de banda como este, en realidad hace que el GC haga más trabajo y, en última instancia, puede terminar perjudicando el rendimiento de sus aplicaciones. Durante la duración del ciclo de recolección de GC, su solicitud está realmente en un estado congelado...cuantos más ciclos de GC se ejecuten, más tiempo que su aplicación pasa congelada.

También hay algunas llamadas nativas a la API de Win32 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 recopilado por gargbage es que no necesita preocuparse (tanto) por cuándo el tiempo de ejecución asigna/desasigna la memoria real; solo necesita preocuparse por asegurarse de que su objeto sepa cómo limpiarse después de sí mismo cuando se le pregunte.

 6
Author: Scott Dorman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-24 09:53:31
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
 3
Author: Darren Kopp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-15 15:32:02

Explicación completa de Joe Duffy sobre " Eliminación, Finalización y Gestión de Recursos":

Anterior en el Framework. NET de por vida, los finalizadores fueron consistentemente denominados destructores por C# programador. A medida que nos volvemos más inteligentes tiempo, estamos tratando de llegar a un acuerdo con el hecho de que el método Dispose es realmente más equivalente a un C++ destructor (deterministic) , mientras que el finalizer es algo enteramente separado (nondeterministic) . Hecho que C# tomó prestado el destructor de C++ la sintaxis (es decir, ~T ()) seguramente tenía al menos un poco que ver con el desarrollo de este nombre inapropiado.

 3
Author: jfs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-26 09:36:18

Escribí un resumen de Destructores y Eliminación y recolección de basura en http://codingcraftsman.wordpress.com/2012/04/25/to-dispose-or-not-to-dispose /

Para responder a la pregunta original:

  1. No trates de manejar tu memoria
  2. Dispose no se trata de gestión de memoria, se trata de gestión de recursos no administrados
  3. Los finalizadores son una parte innata del patrón de eliminación y en realidad ralentizan la liberación de memoria de los objetos administrados (ya que tienen que entrar la cola de finalización a menos que ya se haya Eliminado d)
  4. GC.Recoger es malo, ya que hace que algunos objetos de corta duración parecen ser necesarios por más tiempo y por lo tanto ralentiza su recogida.

Sin embargo, GC.Collect podría ser útil si tuviera una sección de código crítica para el rendimiento y quisiera reducir la probabilidad de que la Recolección de basura lo ralentice. Llamas a eso antes.

Además de eso, hay un argumento a favor de esto 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 la Recolección de basura solo funciona a menos que juegues con ella!

 3
Author: Ashley Frieze,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-02 22:13:37

Realmente no se puede forzar a un GC a limpiar un objeto cuando se quiere, aunque hay formas de forzarlo a correr, nada dice que es limpiar todo el objeto que se quiere/se espera. Lo mejor es llamar a dispose in a try catch ex finaly dispose end try (VB.NET rulz) way. Pero Dispose es para limpiar los recursos del sistema(memoria, controladores, conexiones de base de datos, etc. asignado por el objeto de manera determinista. Dispose no (y no puede) limpiar la memoria utilizada por el objeto en sí, solo el GC puede hacer que.

 2
Author: Booji Boy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-15 15:42:36

Este artículo tiene un tutorial bastante sencillo. Sin embargo, tener para llamar a la GC en lugar de dejar que tome su curso natural es generalmente un signo de mal diseño/gestión de memoria, especialmente si no se están consumiendo recursos limitados (conexiones, manejadores, cualquier otra cosa que típicamente conduce a la implementación de identificable).

¿Qué es lo que hace que necesites hacer esto?

 1
Author: Greg Hurlman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-15 15:34:43

La interfaz identificable 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 basura? De lo contrario, solo asegúrese de que su objeto se instancie lo más tarde posible y salga del alcance lo antes posible.

 1
Author: Tundey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-15 16:48:49

Lo sentimos, pero la respuesta seleccionada aquí es incorrecta. Como algunas personas han declarado posteriormente Dispose y la implementación de IDesposable no tiene nada que ver con liberar la memoria asociada con una clase.NET. Se utiliza principalmente y tradicionalmente para liberar recursos no administrados como manejadores de archivos, etc.

Mientras que su aplicación puede llamar a GC.Collect() para intentar forzar una recolección por parte del recolector de basura, esto solo tendrá un efecto real en aquellos elementos que estén en el nivel de generación correcto en la cola freachable. Por lo tanto, es posible que si ha borrado todas las referencias al objeto, todavía podría ser un par de llamadas a GC.Collect () antes de liberar la memoria real.

No dices en tu pregunta POR qué sientes la necesidad de liberar memoria inmediatamente. 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 memoria.

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

 1
Author: Shaun Austin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-25 21:29:10

@Keith,

Estoy de acuerdo con todas sus reglas excepto #4. La adición de 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 true. 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 se GC ejecuta un ciclo de recolección. Efectivamente, esto significa que su objeto sobrevive un ciclo / generación más de lo que debería para que el finalizador se pueda ejecutar. El finalizador no debe ser considerado como una "red de seguridad".

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

La conclusión es que, no importa qué, el GC solo sabe cómo liberar recursos llamando al método Dispose(y posiblemente al finalizer si se implementa uno). Depende de ese método "hacer lo correcto" y limpiar cualquier recurso no administrado utilizado e instruir a cualquier otro recurso administrado para que llame a su método de Eliminación. Es muy eficiente en lo que hace y puede auto-optimizarse en gran medida, siempre y cuando no sea ayudado por ciclos de colección fuera de banda. Dicho esto, menos que llamar a GC.Recoger explícitamente no tiene control sobre cuándo y en qué orden se eliminarán los objetos y se liberará la memoria.

 1
Author: Scott Dorman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-31 10:26:30

Si no quieres (o no puedes) implementar IDesposable en tu clase, puedes forzar la recolección de basura de esta manera (pero es lenta) -

GC.Collect();
 0
Author: Seibar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-15 15:33:55

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

Nunca quieres llamar a GC.Recoger, se mete con el autoajuste del colector de basura para detectar la presión de la memoria y en algunos casos no hacer otra cosa que aumentar la generación actual de cada objeto en el montón.

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

 0
Author: Brian Leahy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-25 21:18:25

@Keith:

IDisposable es que los recursos gestionados.

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 dispose se ha implementado correctamente, el finalizador intenta invocar Dispose.

Dispose tiene dos trabajos:

  • Recursos no administrados libres, y
  • recursos gestionados anidados libres.

Y aquí su declaración entra en juego porque es cierto que al finalizar, un objeto nunca debe intentar liberar recursos administrados anidados, ya que estos pueden haber sido liberados. Sin embargo, todavía debe liberar recursos no administrados.

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

 0
Author: Konrad Rudolph,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-26 09:11:17

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

Luego, cuando lo implementa, usa el patrón de eliminación de Microsoft (como ya se describió)

  • public Dispose() calls protected Dispose(true) - se ocupa tanto de los recursos administrados como de los no administrados. Llamar Dispose() debería suprimir la finalización.

  • ~Finalize calls protected Dispose(false) - solo trata con recursos no administrados. Esto evita fugas de memoria no administradas si no llama al public Dispose()

~Finalize es lento y no debe usarse a menos que tenga recursos no administrados con los que lidiar.

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 filtrarse, y ~Finalize es la mejor práctica para garantizar que no lo hagan.

En cualquier caso using es la mejor práctica.

 0
Author: Keith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-28 16:06:28

@Curt Hagenlocher - eso es de atrás hacia adelante. No tengo ni idea de por qué tantos lo han votado cuando está mal.

IDisposable es para recursos gestionados.

Los finalizadores son para recursos no administrados.

Siempre y cuando solo uses recursos administrados, tanto @Jon Limjap como yo estamos totalmente en lo correcto.

Para las clases que usan recursos no administrados (y tenga en cuenta que la gran mayoría de las clases. Net no lo hacen) La respuesta de Patrik es completa y mejor practicar.

Evite usar GC.Collect-es una forma lenta de lidiar con los recursos administrados, y no hace nada con los no administrados a menos que haya construido correctamente sus ~Finalizers.


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

 0
Author: Keith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:02:02

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 programación en.NET para incluso recibir la respuesta: use GC.Recoger(). Yo diría que es 99.99% probable que él realmente no necesita usar GC.Collect () en absoluto, como la mayoría de los carteles han señalado.

La respuesta correcta se reduce a 'Dejar que el GC haga su trabajo. Periodo. Tienes otras cosas de las que preocuparte. Pero es posible que desee considerar si y cuándo debe desechar o limpiar objetos específicos, y si necesita implementar IDesposable y posiblemente Finalizar en su clase.'

Con respecto al post 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ívocamente. Es la única regla de los cuatro que no necesita edición en absoluto. Reformularía ligeramente algunas de sus otras reglas para hacerlas más claras, pero son esencialmente correctas si las analizas correctamente, y en realidad leer todo el post para ver cómo se expande en ellos.

  1. Si su clase no usa un recurso no administrado Y tampoco crea instancias de otro objeto de una clase que use, directa o definitivamente, un objeto no administrado (es decir, una clase que implemente Identificable), entonces no habrá necesidad de que su clase implemente Identificable por sí misma, o incluso llame .deshazte de cualquier cosa. (En tal caso, es tonto pensar que realmente NECESITA inmediatamente libera memoria con un GC forzado, de todos modos.)

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

    A) disponer/liberar estos inmediatamente en un contexto local en el que fueron creados, O...

    B) implementar IDesposable en el patrón recomendado dentro del post de Keith, o en unos pocos miles de lugares en Internet, o en literalmente alrededor de 300 libros por ahora.

    B. 1) Además, si (b), y es un recurso no administrado que se ha abierto, tanto IDesposable COMO Finalize DEBEN implementarse SIEMPRE, según la Regla #4 de Keith.
    En este contexto, Finalize absolutamente ES una red de seguridad en un sentido: si alguien crea una instancia de SU objeto identificable que utiliza un recurso no administrado, y no puede llamar a dispose, entonces Finalize es la última oportunidad para que SU objeto cierre el recurso no administrado correctamente.
    (Finalize debe hacer esto llamando a Dispose de tal manera que el método Dispose omite liberar cualquier cosa QUE no sea el recurso no administrado. Alternativamente, si el método Dispose de su objeto ES llamado correctamente por cualquiera que haya instanciado su objeto, entonces 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 el Finalizar en su objeto, lo que significa que el impacto de usar Finalize se reduce si el objeto es dispuesto correctamente por el autor de la llamada. Todos estos puntos están incluidos en el post de Keith, por cierto.)

    B. 2) SI su clase solo está implementando Identificable porque necesita esencialmente pasar un Dispose a un objeto Identificable que ha instanciado, entonces no implemente un método Finalize en su clase en ese caso. Finalize es para manejar el caso de que AMBOS Dispose nunca fueron llamados por cualquiera que haya instanciado su objeto, Y se utilizó un recurso no administrado que aún no se ha publicado.

En resumen, con respecto a El post de Keith, es completamente correcto, y ese post es la respuesta más correcta y completa, en mi opinión. Él puede usar algunas declaraciones cortas que algunos encuentran 'erróneas' u objetan, pero su publicación completa expande el uso de Finalizar completamente, y está absolutamente correcto. Asegúrese de leer su post completo antes de saltar sobre una de las reglas o declaraciones preliminares en su post.

 0
Author: Jaycephus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-23 01:25:58

Si MyClass implementa IDisposable que usted puede hacer precisamente eso.

MyClass.Dispose();

La mejor práctica en C # es:

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

Como eso envuelve la disposición en un intento-finalmente y se asegura de que nunca se pierda.

 -1
Author: Keith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-15 15:32:40