Pregunta

Uso una plantilla de implementación IDisposable predeterminada (patrón) para mi código.

fragmento de código:

public void Dispose()
{
    Dispose(true);

    GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool isDisposing)
{
    if (!this.disposed)
    {
        if (isDisposing)
        {
            //cleanup managed resources
        }

        //cleanup unmanaged resources

        this.disposed = true;
    }
}

Mi pregunta: ¿por qué es la llamada " GC.SuppressFinalize (this) " en el método de disposición pública? Yo pondría " GC.SuppressFinalize (this) " en " if (isDisposing) " Sección del método protegido, después de disponer los recursos gestionados.

Me gusta esto:

protected virtual void Dispose(bool isDisposing)
{
    if (!this.disposed)
    {
       if (isDisposing)
       {
           //cleanup managed resources

           GC.SuppressFinalize(this);
       }

       //cleanup unmanaged resources

       this.disposed = true;
    }
}
¿Fue útil?

Solución

Supongo que es un caso claro de patrón de diseño de plantilla.

Su clase abstracta está diseñada para ocuparse de todas las tareas importantes / necesarias requeridas (aquí, GC.SuppressFinalize (esto)), y permite que una clase derivada anule solo una parte del código.

Hay 2 casos aquí:
Fragmento 1, SuppressFinalize, en Eliminar
Fragmento 2, SuppressFinalize, en Disose (true)

Aquí, Snippet 1, se asegura de que GC.SuppressFinalize siempre se ejecute. Mientras que el fragmento 2, deja la ejecución de GC.SuppressFinalize a merced de clase derivada .

Entonces, al poner GC.SuppressFinalize, en el método Dispose, usted, como diseñador de su clase, siempre se asegurará de que, independientemente del código escrito por las clases derivadas, se ejecute GC.SuppressFinalize.

Esto es solo el beneficio de escribir SuppressFinalize en Disose en lugar de Disose (true).

Otros consejos

El método Dispose (bool isDisposing) no forma parte del IDisposable .

Normalmente llamaría a Dispose (true) desde su Dispose , y llame a Dispose (false) de su finalizador, como una alternativa en el caso donde el objeto aún no ha sido dispuesto.

Llamando a SuppressFinalize le dice al GC que no hay necesidad de llamar al finalizador de su objeto, presumiblemente porque toda la limpieza se realizó cuando se llamó a Dispose .

Si no tiene un finalizador en su clase, entonces no necesita llamar a SuppressFinalize , ¡ya que no hay finalizador para suprimir!

Joe Duffy tiene algunos excelentes pautas sobre la eliminación, finalización, recolección de basura, etc. .

Creo que se podría haber elegido cualquiera de los dos diseños, pero probablemente querían enfatizar " poner todo el código de desasignación en este método " en el método de Dispose protegido, por lo que ponen el otro artefacto de eliminación (Suprimiendo finalización) en otra parte.

También, supongamos que una clase derivada tenía otra razón para llamar al método de Disose protegido, pero todavía quería que se produjera la finalización (por cualquier razón imaginaria, no lo sé).

Causa .Disponer es cuando el código administrado (su código) se deshace del objeto, por lo que se excluye de la finalización. La gente suele crear otra ruta en Dispose (disposición de bool) a través de un finalizador y la llamada no tendría ningún sentido para el finalizador.

La idea es que su código de limpieza solo debe llamarse una vez. Sin embargo, hay dos puntos de entrada: el método Dispose y los finalizadores de objetos. Cuando se llama a Dispose , usted cancela la finalización para que solo se llame una vez al código de limpieza. El código aquí podría ilustrarlo mejor.

Cita:

// NOTE: Leave out the finalizer altogether if this class doesn't 
// own unmanaged resources itself, but leave the other methods
// exactly as they are. 
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top