2011-01-11 10 views
7

Ich habe eine Klasse, die IDisposable implementiert, da es ein privates Mitgliedsfeld "foo" hat, das IDisposable ist (das im Konstruktor initialisiert wird). Ich erhalte unerwartet einen CA2000-Code-Analyse-Fehler, der sicherstellt, dass ich foo entsorge. Allerdings habe ich foo.Dispose() im Dispose() Code meiner Klasse, der sich darum kümmern sollte.Warum bekomme ich CA2000 mit einem privaten Member IDisposable innerhalb meiner IDisposable-Klasse?

Ich habe einige Suche herum und überraschend kann keine Antwort finden. Was mache ich falsch? Offensichtlich fehlt mir etwas Grundlegendes. Wie schreibe ich meinen Code, um dies zu überwinden?

Mein VB-Code:

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 

Antwort

7

Der CA2000 Fehler auf den Behälter bezieht sich nicht IDisposable Umsetzung, sondern die Verwendung einer lokalen, die nicht ordnungsgemäß entsorgt wird. Der Grund dafür ist, dass Sie einen Objektinitialisierer für das Einwegobjekt verwenden. Der eigentliche Code, erhalten erzeugt wird, ist im Wesentlichen die folgenden

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

Dieser Code korrekt durch FxCop gekennzeichnet ist als nicht korrekt ein IDisposable in allen Fällen Entsorgung (es ist möglich, eine Ausnahme von der temp.Name = "hello" Linie auftreten, in dem Fall es würde nicht entsorgt werden).

Das Update ist kein Objektinitialisierer hier zu verwenden und Foo direkt

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

Yuck initialisieren. Nachricht: Verwenden Sie keine Eigenschaft :( –

+0

@Hans, ich denke, es wird das gleiche Verhalten haben, auch wenn es ein Feld ist. Jede Zeile kann möglicherweise eine Ausnahme ('ThreadAbort' zum Beispiel), so würde ich * raten, dass FxCop Ich warte gleichermaßen für Felder und Eigenschaften hier. Habe diese Theorie noch nicht getestet. – JaredPar

+0

Es tut nicht, ich versuchte. –