2009-03-07 19 views

Respuesta

9

Siempre hay un finalizador de la IL - System.Object.Finalize() existe en todas las clases, por lo que si usted hace una clase personalizada, tiene un finalizador desea suprimir. Una vez dicho esto, no todos los objetos se colocan en la cola de finalización, por lo que técnicamente debe suprimir la finalización si implementa su propio finalizador.

Si está implementando IDisposable para envolver recursos no administrados, debe incluir un finalizador, y debe evitar que esto se ejecute, ya que en teoría está haciendo la limpieza cuando se llama al Dispose.

+0

Es cierto. Además, debe tener un finalizador que llame a Dispose(). – configurator

+0

True-Object.Finalize es una operación nula, pero si está implementando IDisposable, está diciendo que tiene recursos para liberar. Desde MSDN, eso significa que siempre debe tener un finalizador para liberarlos, para que se manejen correctamente. Esto significa tener Finalize call Dispose y Dispose suprimir finalización –

+4

@configurator Solo debe tener un finalizador si posee directamente recursos no administrados (como identificadores). Si los posee solo de manera indirecta, p. una referencia a un FileStream, ¿por qué debería escribir algo más que IDisposable.Dispose() {if (fs! = null) {fs.Dispose(); fs = nulo; }}? IMO, StyleCop es una herramienta horrible que obliga a escribir y mantener MUCHO texto inútil, y no agrega ningún valor comercial a cambio. –

2

Todos los objetos tienen un método de finalizador, incluso si no ha implementado uno mediante el uso de un destructor C# (que en realidad no está garantizado para ser llamado por el GC). Es una buena práctica suprimir la llamada si ha implementado IDisposable porque eso significa que ha decidido realizar la finalización explícitamente.

devx article

+0

¿Podría explicar el "no garantizado que el GC lo llame"? –

+0

Durante la finalización del programa, algunos objetos pueden no tener la oportunidad de ejecutar sus finalizadores si la limpieza lleva demasiado tiempo. Eso podría ser a lo que se refiere. –

+0

Sí, eso es a lo que me refería. – x0n

2

No veo ninguna necesidad de llamar a SuprimirFinalizar() si no hay un finalizador definido. Si quiere estar a la defensiva, puede ser bueno tener un finalizador y Dispose(), por lo que no necesita confiar en los clientes para llamar siempre a Dispose(). Entonces no perderás recursos cuando lo olviden.

+0

Si un objeto es "responsable" de otros objetos IDdispositivos, pero no tiene recursos no administrados por sí solo, entonces necesita Eliminar pero no Finalizador. –

20

No hay necesidad de llamar a GC.SuppressFinalize(this) en botar, a menos que:

  • Usted es la clase base que implementa métodos Desechar virtuales destinados a anular (de nuevo, puede que no sea su responsabilidad incluso en este caso, pero puede que desee para hacerlo en ese caso)
  • Usted tiene un finalizador usted mismo. Técnicamente, todas las clases de .NET tiene un finalizador, pero si la única finalizador presente es el de Object, el objeto no se considera necesario finalizar y no se pone en la lista de finalización en GC

I diría, asumiendo que no tiene ninguno de los casos anteriores, que puede ignorar ese mensaje de forma segura.

+1

¿Cuándo debería una clase derivada * SIEMPRE * agregar un finalizador a una clase base no trivial? ¿Por qué agregar código para permitir que una clase derivada haga algo que nunca debería hacer? – supercat

+0

@supercat Si una clase derivada posee recursos no administrados, debe tener un finalizador para garantizar que se liberen. Si el objeto siempre se usa correctamente (con una instrucción try-finally o, de manera equivalente, using) Dispose hará la limpieza y suprimirá el finalizador, pero el finalizador asegura que los recursos no administrados se liberen eventualmente (cuando el objeto es basura). incluso si Dispose nunca se llamó (p. ej., debido a una excepción y a la falta de protección de un bloque de código). –

+1

@TheDag: cada recurso no administrado que necesita la limpieza del finalizador casi siempre debe estar encapsulado dentro de su propio objeto, que debe derivarse de 'Objeto', o un tipo base abstracto diseñado explícitamente para ayudar a dicha limpieza. El tipo resultante sería entonces un recurso gestionado, al que el tipo más grande podría retener una referencia. La limpieza de la finalización sería atendida por el objeto de encapsulado más pequeño; el objeto más grande no necesitaría un finalizador. – supercat

Cuestiones relacionadas