2011-01-11 14 views
7

Tengo una clase que implementa IDisposable porque tiene un campo miembro privado "foo" que es IDisposable (que se inicializa en el constructor). Estoy recibiendo inesperadamente un error de análisis de código CA2000, que quiere que me asegure de deshacerme de foo. Sin embargo, tengo foo.Dispose() en el código Dispose() de mi clase, que debería encargarse de esto.¿Por qué estoy recibiendo CA2000 con un miembro privado IDisposable dentro de mi clase IDisposable?

Realicé algunas búsquedas y, sorprendentemente, no puedo encontrar una respuesta. ¿Qué estoy haciendo mal? Claramente me falta algo básico. ¿Cómo escribo mi código para superar esto?

Mi código VB:

Public Class Bar 
    Implements IDisposable 

    Private Foo As SomeDisposableThing 

    Public Sub New() 
     Foo = New SomeDisposableThing() With {.name = "hello"} 
    End Sub 

    '''' snip '''' 

    Private disposedValue As Boolean = False  ' To detect redundant calls ' 

    Protected Overridable Sub Dispose(ByVal disposing As Boolean) 
     If Not Me.disposedValue Then 
      If disposing Then 
       If Foo IsNot Nothing Then Foo.Dispose() 
      End If 
     End If 
     Me.disposedValue = True 
    End Sub 

    Public Sub Dispose() Implements IDisposable.Dispose 
     Dispose(True) 
     GC.SuppressFinalize(Me) 
    End Sub 

End Class 

Respuesta

7

El error CA2000 no se refiere a la implementación del contenedor IDisposable sino más bien el uso de un local que no está dispuesto correctamente. El motivo es que está utilizando un inicializador de objetos en el objeto desechable. El código real que se generará es esencialmente el siguiente

Dim temp = New SomethingDisposable() 
temp.Name = "hello" 
Foo = temp 

Este código se encuentra en posición correcta por FxCop no eliminación adecuada de un IDisposable en todos los casos (es posible que una excepción que se produzca en la línea temp.Name = "hello" en cuyo caso no sería eliminado).

La solución es no utilizar un inicializador de objeto aquí e inicializar Foo directamente

Foo = New SomethingDisposable() 
Foo.Name = "hello" 
+0

Yuck. Mensaje: no use una propiedad :( –

+0

@Hans, creo que tendrá el mismo comportamiento incluso si es un campo. Cualquier línea puede lanzar una excepción ('ThreadAbort', por ejemplo), así que * adivinaría * que FxCop advertiría igualmente para los campos y propiedades aquí. Sin embargo, aún no he probado esa teoría. – JaredPar

+0

No, lo intenté. –

Cuestiones relacionadas