Freigeben über


CA2000: Objekte verwerfen, bevor Bereich verloren geht

TypeName

DisposeObjectsBeforeLosingScope

CheckId

CA2000

Kategorie

Microsoft.Reliability

Unterbrechende Änderung

Nicht unterbrechend

Ursache

Ein lokales Objekt eines IDisposable-Typs wird erstellt. Das Objekt wird jedoch erst verworfen, nachdem alle Verweise auf das Objekt sich außerhalb des Gültigkeitsbereichs befinden.

Regelbeschreibung

Wenn ein verwerfbares Objekt nicht explizit verworfen wird, bevor alle Verweise auf das Objekt sich außerhalb des Gültigkeitsbereichs befinden, wird das Objekt zu einem nicht genau festgelegten Zeitpunkt verworfen, wenn der Garbage Collector den Finalizer des Objekts ausführt. Da eine Ausnahme auftreten kann, durch die die Ausführung des Objektfinalizers verhindert wird, sollte das Objekt stattdessen explizit verworfen werden.

Behandeln von Verstößen

Um einen Verstoß gegen diese Regel zu beheben, rufen Sie Dispose für das Objekt auf, bevor sich alle Verweise darauf außerhalb des Gültigkeitsbereichs befinden.

Beachten Sie, dass Sie die using-Anweisung (Using in Visual Basic) zum Umschließen von Objekten verwenden können, die IDisposable implementieren. Auf diese Weise umschlossene Objekte werden nach Abschluss des using-Blocks automatisch verworfen.

Die folgenden Situationen sind einige Situationen, wo die using-Anweisung nicht genügt, um IDisposable-Objekte zu schützen, und bewirken kann, dass CA2000 ausgelöst wird.

  • Ein verwerfbares Objekt zurückzugeben erfordert, dass das Objekt in einem try/finally-Block außerhalb eines using-Blocks erstellt wird.

  • Member eines verwerfbaren Objekts sollten nicht im Konstruktor einer using-Anweisung initialisiert werden.

  • Das Schachteln von Konstruktoren, die nur von einem Ausnahmehandler geschützt sind. Beispiel:

    using (StreamReader sr = new StreamReader(new FileStream("C:\myfile.txt", FileMode.Create)))
    { ... }
    

    bewirkt, dass CA2000 ausgelöst wird, da ein Fehler in der Konstruktion des StreamReader-Objekts dazu führen kann, dass das FileStream-Objekt nie geschlossen wird.

  • Dynamische Objekte sollten ein Schattenobjekt verwenden, um das Freigabe-Muster von IDisposable-Objekten zu implementieren.

Wann sollten Warnungen unterdrückt werden?

Unterdrücken Sie keine Warnung dieser Regel, es sei denn, Sie haben eine Methode für das Objekt aufgerufen, von der Dispose aufgerufen wird, z. B. Close..

Verwandte Regeln

CA2213: Verwerfbare Felder verwerfen

CA2202: Objekte nicht mehrmals verwerfen

Beispiel

Wenn Sie eine Methode implementieren, die ein verwerfbares Objekt zurückgibt, verwenden Sie einen try/finally-Block ohne einen catch-Block, um sicherzustellen, dass das Objekt verworfen wird. Mit einem try/finally-Block lassen Sie Ausnahmen zu, die am Fehlerpunkt ausgelöst werden sollen, und stellen sicher, dass das Objekt freigegeben wird.

In der OpenPort1-Methode kann der Aufruf zum Öffnen des ISerializable-Objekts SerialPort oder der Aufruf von SomeMethod fehlschlagen. Eine CA2000-Warnung wird für diese Implementierung ausgelöst.

In der OpenPort2-Methode werden zwei SerialPort-Objekte deklariert und auf NULL festgelegt:

  • tempPort, der verwendet wird, um zu testen, ob die Methodenoperationen erfolgreich sind.

  • port, der für den Rückgabewert der Methode verwendet wird.

Der tempPort wird erstellt und wird in einem try geöffnet, und jede andere erforderliche Arbeit wird im gleichen try ausgeführt. Am Ende des try-Blocks wird dem port-Objekt, das zurückgegeben wird, der geöffnete Port zugewiesen, und das tempPort-Objekt wird auf null festgelegt.

Der finally-Block überprüft den Wert von tempPort. Wenn nicht NULL, ist eine Operation in der Methode fehlgeschlagen und tempPort wird geschlossen, um sicherzustellen, dass alle Ressourcen freigegeben werden. Das zurückgegebene Portobjekt enthält das geöffnete SerialPort-Objekt, wenn die Operationen der Methode erfolgreich waren, oder es ist NULL, wenn eine Operation fehlschlug.

Public Function OpenPort1(ByVal PortName As String) As SerialPort

   Dim port As New SerialPort(PortName)
   port.Open()    'CA2000 fires because this might throw
   SomeMethod()   'Other method operations can fail
   Return port

End Function


Public Function OpenPort2(ByVal PortName As String) As SerialPort

   Dim tempPort As SerialPort = Nothing
   Dim port As SerialPort = Nothing

   Try
      tempPort = New SerialPort(PortName)
      tempPort.Open()
      SomeMethod()
      'Add any other methods above this line
      port = tempPort
      tempPort = Nothing

   Finally
      If Not tempPort Is Nothing Then
         tempPort.Close()
      End If


   End Try

   Return port

End Function

Public Function CreateReader1(ByVal x As Integer) As StreamReader
   Dim local As New StreamReader("C:\Temp.txt")
   x += 1
   Return local
End Function


Public Function CreateReader2(ByVal x As Integer) As StreamReader
   Dim local As StreamReader = Nothing
   Dim localTemp As StreamReader = Nothing
   Try
      localTemp = New StreamReader("C:\Temp.txt")
      x += 1
      local = localTemp
      localTemp = Nothing
      Finally
         If (Not (localTemp Is Nothing)) Then
            localTemp.Dispose()
         End If
   End Try
   Return local
End Function

public SerialPort OpenPort1(string portName)
{
   SerialPort port = new SerialPort(portName);
   port.Open();  //CA2000 fires because this might throw
   SomeMethod(); //Other method operations can fail
   return port;
}

public SerialPort OpenPort2(string portName)
{
   SerialPort tempPort = null;
   SerialPort port = null;
   try
   {
      tempPort = new SerialPort(portName);
      tempPort.Open();
      SomeMethod();
      //Add any other methods above this line
      port = tempPort;
      tempPort = null;

   }
   finally
   {
      if (tempPort != null)
      {
         tempPort.Close();
      }
   }
   return port;
}

Standardmäßig überprüft der Visual Basic-Compiler auf Überläufe mit allen arithmetischen Operatoren. Daher kann jede arithmetische Visual Basic-Operation eine OverflowException auslösen. Dies kann zu unerwarteten Regelverletzungen führen, z. B. CA2000. Die folgende CreateReader1-Funktion erzeugt z. B. eine CA2000-Verletzung, da der Visual Basic-Compiler einen Überlauf ausgibt, der Anweisung auf die Hinzufügung überprüft, die eine Ausnahme auslösen könnte, die bewirken würde, dass der StreamReader nicht freigegeben wird.

Um dieses zu korrigieren, können Sie das Ausgeben von Überlaufprüfungen durch den Visual Basic-Compiler im Projekt deaktivieren, oder Sie können den Code wie die folgende CreateReader2-Funktion ändern.

Um die ausgegebenen Erweiterungsprüfungen zu deaktivieren, klicken Sie mit der rechten Maustaste im Fenster "Projektmappen-Explorer" auf das Projekt, und klicken Sie anschließend auf Eigenschaften. Klicken Sie auf Kompilieren, klicken Sie auf Erweiterte Kompilierungsoptionen, und aktivieren Sie dann Überprüfungen auf Ganzzahlüberlauf entfernen.

Siehe auch

Referenz

IDisposable

Implementieren der Methoden "Finalize" und "Dispose" zum Bereinigen von nicht verwalteten Ressourcen