Sdílet prostřednictvím


CA2000: Vyřazení objekty před ztrátou oboru

TypeName

DisposeObjectsBeforeLosingScope

CheckId

CA2000

Kategorie

Microsoft.Reliability

Narušující změna

Nenarušující

Příčina

Je vytvořen místní objekt typu IDisposable, ale není uvolněn před tím, než budou všechny odkazy na objekt mimo rozsah.

Popis pravidla

Pokud není jednorázový objekt explicitně odstraněn před tím, než budou všechny odkazy mimo rozsah, bude odstraněn v době, kdy bude spuštěno uvolňování paměti finalizační metodou objektu.Protože může dojít k mimořádné události, která zabrání spuštění finalizační metody objektu, měl by místo toho být objekt explicitně odstraněn.

Jak vyřešit porušení

Pro vyřešení porušení tohoto pravidla je zapotřebí zavolat na objekt Dispose před tím, než budou všechny odkazy na něj mimo rozsah.

Všimněte si, že můžete použít příkaz using (Using v Visual Basic) pro zabalení objektů, které implementují IDisposable.Objekty, které jsou zabaleny tímto způsobem budou automaticky odstraněny při uzavření bloku using.

Následují příklady ukazují situace s nedostatečnou ochranu objektů IDisposable a vyvolání CA2000 při použití příkazu using.

  • Vracení jednorázového objektu vyžaduje, aby byl objekt zkonstruován v rámci bloku try/finally mimo blok using.

  • Inicializace členů jednorázového objektu by neměla být provedena v rámci konstruktoru příkazu using.

  • Vnořené konstruktory, které jsou chráněny pouze jednou obslužnou rutinou výjimky.Příklad:

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

    Způsobí výskyt CA2000, protože selhání vytvoření objektu StreamReader FileStream může vést k tomu, že objekt FileStream nebude nikdy uzavřen.

  • Dynamické objekty by měly pro implementaci vzoru odstranění objektů IDisposable používat stínový objekt.

Kdy potlačit upozornění

Nepotlačovat upozornění tohoto pravidla, pokud nebyla zavolána metoda na objekt, který volá Dispose, jako například Close.

Související pravidla

CA2213: By odbyt na jedno použití polí

CA2202: Neodstraňovat objekty několikrát

Příklad

Při implementaci metody, která vrací objekt odstranění je zapotřebí použít blok try/finally bez použití bloku catch pro ujištění se, zda je objekt uvolněn.Pomocí bloku try/finally lte povolit vyvolání výjimek v místě selhání pro ujištění se, zda je objekt uvolněn.

V metodě OpenPort1 může volání pro otevření objektu ISerializable, SerialPort nebo volání SomeMethod vést k selhání.V této implementaci je vyvoláno upozornění CA2000.

V metodě OpenPort2 jsou deklarovány dva objekty SerialPort a jsou nastaveny na hodnotu null:

  • tempPort, který se používá k testování, zda proběhly operace metody úspěšně.

  • port, který se používá pro návratovou hodnotu metody.

tempPort je vytvořen a otevřen v rámci bloku try a jakákoliv jiná požadovaná činnost je vykonána v rámci stejného blokutry.Na konci bloku try je otevřený port přiřazen objektu port, který bude vrácen a objekt tempPort je nastaven na null.

Blok finally kontroluje hodnotu tempPort.Pokud není null, operace v rámci metody selhala a tempPort je zavřen pro ujištění se, aby nebyly uvolněny jakékoliv prostředky.Vrácený objekt portu bude obsahovat otevřený objekt SerialPort pokud byly operace metody úspěšné nebo bude null, pokud se operace nezdaří.

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

Standardně má kompilátor Visual Basic všechny aritmetické operátory kontrolovány vůči přetečení.A proto může jakákoliv aritmetická operace jazyka Visual Basic vyvolat OverflowException.To může vést k neočekávaným porušením pravidel, například CA2000.Například následující funkce CreateReader1 ohlásí porušení CA2000 protože kompilátor jazyka Visual Basic generuje dodatečnou instrukci kontroly přetečení, která může vyvolat výjimku, která může způsobit, že StreamReader nebude odstraněn.

Pro vyřešení toho problému lze zakázat generování kontrol přetečení kompilátorem jazyka Visual Basic v rámci projektu nebo lze provést modifikaci kódu, jak je tomu ve funkci CreateReader2.

Pro zakázání generování kontrol přetečení, klikněte pravým tlačítkem myši na název projektu v rámci Průzkumníku řešení a následně klikněte na Vlastnosti.Klikněte na tlačítko Kompilovat, následně klikněte na Rozšířené možnosti kompilace a poté zaškrtněte Odebrat kontrolu přetečení celých čísel.

Viz také

Referenční dokumentace

IDisposable

Implementing Finalize and Dispose