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.