2010-06-11 29 views
8

En mis métodos de eliminación (como el siguiente), cada vez que deseo llamar a algúnObj.Dispose() también tengo una comprobación para algúnObj! = Null.Eliminación de los miembros que implementan IDisposable

¿Eso se debe a un mal diseño de mi parte? ¿Existe una manera más clara de determinar si se llama a Deshacerse de todos los miembros (implementación IDisposable) que se usa en un objeto sin tener el riesgo de excepción de NullReference?

protected void Dispose(bool disposing) 
     { 
      if (disposing) 
      { 
       if (_splitTradePopupManager != null) 
       { 
        _splitTradePopupManager.Dispose(); 
       } 
      } 
     } 

Gracias por su interés.

Respuesta

4

Tal vez alguien más pueda intervenir al respecto, pero personalmente no creo que sea un defecto de diseño, sino la forma más segura de hacerlo.

Dicho esto, nada te detiene de envolver su cheque null y Dispose llamada en un método conveniente:

private void DisposeMember(IDisposable member) 
{ 
    if (member != null) 
     member.Dispose(); 
} 

A continuación, el método Dispose podía mirar un poco más limpia:

protected void Dispose(bool disposing) 
{ 
    if (disposing) 
    { 
     DisposeMember(_splitTradePopupManager); 
     DisposeMember(_disposableMember2); 
     DisposeMember(_disposableMember3); 
    } 
} 

Como un agregado Además, esto también resuelve una posible condición de carrera en tu código original. Si se ejecuta en un contexto multiproceso, el patrón if (_field != null) _field.Dispose() puede dar como resultado un NullReferenceException cuando _field se establece en null entre el cheque y la eliminación (raro, pero posible). Pasar _field como argumento a un método como DisposeMember copia la referencia a una variable local en el método, eliminando esta posibilidad, poco probable como es.

+1

De acuerdo con que no es un defecto de diseño. Tal vez soy demasiado cauteloso, pero prefiero tener una verificación nula incluso cuando sé fehacientemente que el objeto nunca será nulo cuando se trate de desechables. –

+0

@ccomet: +1, tengo el mismo pensamiento (demasiado cauteloso) en el fondo mientras llamo a Dispose() sobre un objeto. –

0

¡Solo tú conoce la respuesta a esta pregunta!

Sin ver toda su clase, es difícil que alguien más sepa si es posible que esos miembros sean nulos alguna vez cuando se llame a Dispose.

(Por supuesto, como regla general, siempre es posible que un tipo de referencia o tipo de valor anulable a ser nula, por lo que es probablemente una buena práctica incluir siempre los cheques nulos todos modos.)

0

La única otra opción que podría pensar sería crear un método de ayuda DisposeParameter que tenga un objeto como parámetro y solo verifique si es nulo y desecharlo de otro modo. De esta manera, solo necesitaría una línea de código para deshacerse de ella, pero no estoy seguro de si la haría más legible.

-1

Pruebe esto.

protected void Dispose(bool disposing) 
    { 
     if (disposing) 
     { 
      //for all members.. 
      if (null != member && member is IDisposible) 
      { 
       member.Dispose(); 
      } 
     } 
    } 
+0

No estoy seguro de entender lo que está sugiriendo aquí. –

+0

alguien puede justificar el voto negativo? –

+4

No fui yo, pero comprobar si el miembro es un 'IDisposable' es un poco tonto, porque una llamada a' member.Dispose() 'no se compilaría cuando' member' no fuera un tipo desechable. – Steven

9

me gusta la solución de @ Dan Tao, pero es mucho mejor como un método de extensión, la OMI:

public static void SafeDispose(this IDisposable obj) 
{ 
    if (obj != null) 
     obj.Dispose(); 
} 

Ahora usted puede simplemente llamar en cualquier member.SafeDispose()IDisposable en su programa sin la preocupación. :)

+0

Eso no arrojará una excepción de referencia nula cuando intenta llamar al método de extensión? Editar-- Escribí una aplicación de prueba rápida, ¡y funciona genial! –

+0

No, no lo hará. Usé un enfoque similar en un proyecto (DisposeIfNotNull()). –

+2

¡No! Como el operador punto es solo azúcar sintáctica para un método estático, funciona muy bien. :) – tzaman

Cuestiones relacionadas