Udostępnij za pośrednictwem


CA2000: Usuwanie obiektów przed utratą zakresu

TypeName

DisposeObjectsBeforeLosingScope

CheckId

CA2000

Kategoria

Microsoft.Reliability

Zmiana kluczowa

Niekluczowa

Przyczyna

Lokalny obiekt typu IDisposable został utworzony, ale obiekt nie jest usuwany, aż wszystkie odwołania do obiektu będą poza zakresem.

Opis reguły

Jeśli obiekt usuwalny nie jest jawnie usuwany zanim wszystkie odwołania do niego są poza zakresem, obiekt zostanie usunięty w nieokreślonym czasie, gdy moduł usuwający elementy bezużyteczne pamięci uruchomi finalizator obiektu.Ponieważ może wystąpić nieoczekiwane zdarzenie, które uniemożliwi uruchomienie finalizatora, obiekt należy jawnie usunąć.

Jak naprawić naruszenia

Aby naprawić naruszenie tej zasady, należy wywołać dla obiektu Dispose zanim wszystkie odwołania do tego obiektu znajdą się poza zakresem.

Należy zauważyć, że można użyć instrukcji using (Using w Visual Basic) aby otoczyć obiekty implementujące IDisposable.Obiekty, które są pakowane w ten sposób automatycznie zostaną usunięte po zamknięciu bloku using.

Poniżej opisano sytuacje, w których instrukcja using nie wystarcza do ochrony obiektów IDisposable i może spowodować wystąpienie CA2000.

  • Zwracanie obiektu usuwalnego wymaga, aby obiekt został skonstruowany w bloku try/finally poza blokiem using.

  • Inicjowanie elementów członkowskich usuwalnego obiektu nie powinno być dokonywane w konstruktorze przy użyciu instrukcji using.

  • Zagnieżdżone konstruktory, które są chronione tylko przez jeden blok obsługi wyjątków.Na przykład:

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

    powoduje CA2000, ponieważ błąd podczas tworzenia obiektu StreamReader może spowodować, że obiekt FileStream nigdy nie zostanie zamknięty.

  • Obiekty dynamiczne powinny używać obiektu cienia do zaimplementowania wzorca usuwanie obiektów IDisposable.

Kiedy pominąć ostrzeżenia

Nie należy pomijać ostrzeżenia tej reguły, chyba że wywołano metodę na obiekcie, która wywołuje Dispose, jak na przykład Close, bądź jeśli metoda, która wywołała ostrzeżenie zwróci obiekt IDisposable otaczający Twój obiekt.

Powiązane reguły

CA2213: Pola usuwalne powinny zostać usunięte

CA2202: Nie należy usuwać obiektów wiele razy

Przykład

Jeśli implementujesz metodę, która zwraca obiekt usuwalny, użyj bloku try/finally bez bloku catch aby upewnić się, że obiekt jest usuwany.Poprzez użycie bloku try/finally, zezwala się na zgłaszanie wyjątków w punkcie usterki i zapewnia się, że obiekt jest usuwany.

W metodzie OpenPort1 wywołanie otwarcia obiektu ISerializable portu SerialPort lub wywołanie SomeMethod może się nie powieść.Ostrzeżenie CA2000 jest wywoływane dla tej implementacji.

W metodzie OpenPort2 dwa obiekty portu SerialPort są deklarowane i ustawiane na wartość null:

  • tempPort, służący do sprawdzenia, że operacje metody powiodły się.

  • port, który jest używany dla wartości zwracanej metody.

tempPort jest tworzony i otwierany w bloku try oraz wszelka inna wymagana praca jest wykonywana w tym samym bloku try.Na koniec bloku try otwarty port jest przypisywany do obiektu port, który zostanie zwrócony i obiekt tempPort jest ustawiany na wartość null.

Blok finally sprawdza wartość tempPort.Jeśli nie jest równa null, operacja w metodzie nie powidła się i tempPort zostaje zamknięty, aby upewnić się, że wszystkie zasoby zostaną zwolnione.Obiekt zwrócony portu będzie zawierać otwarty obiekt portu SerialPort jeśli operacje metody powiodą się lub przyjmie wartość null, jeśli operacja nie powiedzie się.

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;
}

Domyślnie kompilator Visual Basic sprawdza przepełnienie dla wszystkich operatorów arytmetycznych.Dlatego każda operacja arytmetyczna Visual Basic może zgłosić OverflowException.Mogłoby to doprowadzić do nieoczekiwanego naruszenia zasad, takich jak CA2000.Na przykład poniższa funkcja CreateReader1 spowoduje naruszenie CA2000 ponieważ kompilator języka Visual Basic emituje instrukcję sprawdzania przepełnienia dla dodawania, która może zgłosić wyjątek, który może spowodować, że obiekt StreamReader nie zostanie usunięty.

Aby rozwiązać ten problem, można wyłączyć emisję kontroli przepełnienia przez kompilator Visual Basic w projekcie lub można zmodyfikować kod tak jak w funkcji CreateReader2.

Aby wyłączyć emisję sprawdzania przepełnienia, kliknij prawym przyciskiem myszy nazwę projektu w oknie Eksploratora rozwiązania, a następnie kliknij przycisk Właściwości.Kliknij Skompiluj, kliknij Zaawansowane opcje kompilacji, a następnie sprawdź Usuń sprawdzenia przepełnienia liczb całkowitych.

Zobacz też

Informacje

IDisposable

Inne zasoby

Implementing Finalize and Dispose