He estado solucionando algunos problemas de pérdida de memoria en una aplicación de winforms y he notado algunos objetos desechables que no están explícitamente eliminados (el desarrollador no ha llamado método Dispose). La implementación del método Finalize tampoco ayuda porque no está incluida en la cláusula if (disposing)
. Todo el anulamiento de registro y eliminación de eventos estáticos se ha incluido en la cláusula if (disposing)
. La mejor práctica es invocar el Dispose si el objeto es desechable, pero lamentablemente esto sucede a vecesImplementación IDisposable: qué debe ir en 'si (eliminación)'
Si hay objetos no administrados, controladores de eventos estáticos y algunas colecciones administradas que deben borrarse al deshacerse. ¿Cuál es la manera de decidir qué debería entrar y qué debería salir de la cláusula if (disposing)
?
// Dispose(bool disposing) executes in two distinct scenarios.
// If disposing equals true, the method has been called directly
// or indirectly by a user's code. Managed and unmanaged resources
// can be disposed.
// If disposing equals false, the method has been called by the
// runtime from inside the finalizer and you should not reference
// other objects. Only unmanaged resources can be disposed.
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
// Free other state (managed objects).
}
// Free your own state (unmanaged objects).
// Set large fields to null.
disposed = true;
}
}
It says objetos gestionados debería en if (disposing)
que ejecuta normalmente sólo cuando llamar explícitamente al método Dispose por el desarrollador. Si se ha implementado el método Finalize y el desarrollador se olvida de llamar al método Dispose, la ejecución que viene aquí a través del Finalizer no entra en la sección if (disposing)
.
A continuación se presentan mis preguntas.
Si tengo controladores de eventos estáticos que causan pérdidas de memoria, ¿dónde debo anular el registro? ¿Dentro o fuera de la cláusula
if (disposing)
?Si tengo algunas colecciones que causan pérdidas de memoria, ¿dónde debo borrarlas? ¿Dentro o fuera de la cláusula
if (disposing)
?Si utilizo objetos desechables de terceros (p. Ej .: DevExpress winform controls) no estoy seguro de que sean objetos gestionados o no gestionados. Digamos que quiero eliminarlos cuando elimine un formulario. ¿Cómo puedo saber qué se gestionan y qué objetos no gestionados? Ser desechable no dice eso? En tales casos, ¿cómo decidir qué debería entrar y qué debería salir de la cláusula
if (disposing)
?Si no estoy seguro de que algo gestionados o no lo pueden ser las malas consecuencias de la eliminación/limpieza/anular el registro-eventos fuera de la cláusula
if (disposing)
? Digamos que comprueba nulo antes de deshacerse?
Editar
Lo que quiero decir como un evento Anular el registro es algo parecido a continuación. Publisher es una instancia de larga duración y la línea inferior está en el constructor del suscriptor. En este caso, el suscriptor debe anular el registro del evento y disponerlo ante el editor.
publisher.DoSomeEvent += subscriber.DoSomething;
No es infrecuente que las instancias se suscriban a eventos estáticos. Tales instancias deben darse de baja dentro de la cláusula if (Disposing). – supercat