Comience con estas clases simples ...
Digamos que tengo un conjunto simple de clases como esta:
class Bus
{
Driver busDriver = new Driver();
}
class Driver
{
Shoe[] shoes = { new Shoe(), new Shoe() };
}
class Shoe
{
Shoelace lace = new Shoelace();
}
class Shoelace
{
bool tied = false;
}
A Bus
tiene a Driver
, Driver
tiene dos Shoe
s, cada uno Shoe
tiene a Shoelace
. Todo muy tonto.
Agregue un objeto IDisposable a Shoelace
Más tarde decido que alguna operación en el Shoelace
podría ser multiproceso, así que agrego un EventWaitHandle
para que los hilos se comuniquen. Entonces Shoelace
ahora se ve así:
class Shoelace
{
private AutoResetEvent waitHandle = new AutoResetEvent(false);
bool tied = false;
// ... other stuff ..
}
Implemento IDisposable en Cordón
Pero ahora FxCop de Microsoft se quejará: "Implemente IDisposable en 'Shoelace' porque crea miembros de los siguientes tipos de IDisposable: 'EventWaitHandle'".
Está bien, puedo aplicar IDisposable
en Shoelace
y mi clase se convierte en poco aseado este horrible desastre:
class Shoelace : IDisposable
{
private AutoResetEvent waitHandle = new AutoResetEvent(false);
bool tied = false;
private bool disposed = false;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~Shoelace()
{
Dispose(false);
}
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
if (waitHandle != null)
{
waitHandle.Close();
waitHandle = null;
}
}
// No unmanaged resources to release otherwise they'd go here.
}
disposed = true;
}
}
O (como lo señalaron los comentaristas) ya que en Shoelace
sí mismo no tiene recursos no administrados, podría usar la implementación de disposición más simple sin necesidad de Dispose(bool)
Destructor y:
class Shoelace : IDisposable
{
private AutoResetEvent waitHandle = new AutoResetEvent(false);
bool tied = false;
public void Dispose()
{
if (waitHandle != null)
{
waitHandle.Close();
waitHandle = null;
}
GC.SuppressFinalize(this);
}
}
Mire con horror cómo se propaga IDisposable
Correcto, eso es todo arreglado. Pero ahora FxCop se quejará de que Shoe
crea un Shoelace
, por Shoe
lo que IDisposable
también debe ser .
Y Driver
crea Shoe
así Driver
debe ser IDisposable
. Y Bus
crea Driver
así Bus
debe ser IDisposable
y así sucesivamente.
De repente, mi pequeño cambio Shoelace
me está causando mucho trabajo y mi jefe se pregunta por qué tengo que pagar Bus
para hacer un cambio Shoelace
.
La pregunta
¿Cómo evita esta propagación IDisposable
, pero se asegura de que sus objetos no gestionados se eliminen correctamente?