2011-01-11 3 views
7

Ho una classe che implementa IDisposable perché ha un campo membro privato "foo" che è IDisposable (che è inizializzato nel costruttore). Inaspettatamente sto ottenendo un errore di analisi del codice CA2000, che mi chiede di essere sicuro di disporre di foo. Tuttavia, ho foo.Dispose() nel codice Dispose() della mia classe, che dovrebbe occuparsi di questo.Perché ricevo CA2000 con un membro privato IDisposable all'interno della mia classe IDisposable?

Ho fatto qualche ricerca in giro e sorprendentemente non riesco a trovare una risposta. Che cosa sto facendo di sbagliato? Chiaramente mi manca qualcosa di base. Come scrivo il mio codice per superare questo?

mio codice 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 

risposta

7

L'errore CA2000 non si riferisce al contenitore attuazione IDisposable ma piuttosto l'uso di un locale che non viene correttamente smaltito. Il motivo è che si sta utilizzando un inizializzatore di oggetti sull'oggetto usa e getta. Il codice che andranno generato è essenzialmente il seguente

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

Questo codice è correttamente contrassegnato da FxCop non corretto smaltimento di un IDisposable in tutti i casi (è possibile una deroga avvenga sulla linea temp.Name = "hello" nel qual caso non sarebbe disposto).

La correzione è di non utilizzare un inizializzatore oggetto qui ed inizializzare Foo direttamente

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

Yuck. Messaggio: non usare una proprietà :( –

+0

@Hans, penso che avrà lo stesso comportamento anche se si tratta di un campo.Qualsiasi linea può potenzialmente generare un'eccezione ('ThreadAbort' per esempio) quindi vorrei * supporre * che FxCop Avrei avvertito ugualmente per i campi e le proprietà qui.Tuttavia non ho ancora provato questa teoria. – JaredPar

+0

Non lo so, ho provato .. –