Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
| Tulajdonság | Érték |
|---|---|
| Szabályazonosító | CA2000 |
| Cím | Objektumok eltávolítása a hatókörből való kilépés előtt |
| Kategória | Megbízhatóság |
| A javítás romboló vagy nem romboló | Nem törhető |
| Alapértelmezés szerint engedélyezve a .NET 10-ben | Nem |
| Alkalmazandó nyelvek | C# és Visual Basic |
Ok
Létrejön egy IDisposable helyi típusú objektum, de az objektum nem lesz megsemmisítve, mielőtt az objektumra mutató összes hivatkozás hatókörön kívül esik.
Ez a szabály alapértelmezés szerint a teljes kódbázist elemzi, de ez konfigurálható.
Szabály leírása
Ha egy eldobható objektum nincs explicit módon megsemmisítve, mielőtt az összes rá mutató hivatkozás hatókörön kívül lenne, az objektumot meghatározatlan időpontban kell megsemmisíteni, amikor a szemétgyűjtő futtatja az objektum véglegesítőjét. Mivel előfordulhat olyan kivételes esemény, amely megakadályozza az objektum véglegesítőjének futását, az objektumot explicit módon kell megsemmisíteni.
Különleges esetek
A CA2000 szabály akkor sem aktiválja az alábbi típusú helyi objektumokat, ha az objektum nincs megsemmisítve:
- System.IO.Stream
- System.IO.StringReader
- System.IO.TextReader
- System.IO.TextWriter
- System.Resources.IResourceReader
Ha egy ilyen típusú objektumot átad egy konstruktor paramétereként, majd hozzárendeli egy mezőhöz, ez azt jelenti, hogy a felelősség az erőforrások felszabadításáért az újonnan létrehozott típusra száll át. Vagyis az újonnan létrehozott típus felelős az objektum eltávolításáért. Ha a kód átad egy ilyen típusú objektumot egy konstruktornak, akkor a CA2000 szabály megsértése akkor sem történik meg, ha az objektum nincs megsemmisítve, mielőtt az összes hivatkozás hatókörén kívül lenne.
Szabálysértések kijavítása
A szabály megsértésének kijavításához hívja meg Dispose az objektumot, mielőtt az összes rá mutató hivatkozás hatókörön kívül lenne.
A using utasítással (Using a Visual Basicben) körbefuttathatja azokat az objektumokat, amelyek megvalósítják a IDisposable-ot. Az ilyen módon burkolt objektumok a csoport végén automatikusan megsemmisítve lesznek. A következő helyzeteket azonban nem, vagy nem lehet utasítással using kezelni:
Egy eldobható objektum visszaadásához az objektumot a
try/finallyblokkban kell létrehozni, azon kívül esőusingblokkon kívül.Ne inicializálja egy eldobható objektum tagjait a
usingutasítás konstruktorában.Ha a csak egy kivételkezelő által védett konstruktorok egy
usingutasítás beszerzési részében vannak beágyazva, a külső konstruktor meghibásodása azt eredményezheti, hogy a beágyazott konstruktor által létrehozott objektum soha nem lesz bezárva. Az alábbi példában a StreamReader konstruktor meghibásodása azt eredményezheti, hogy az FileStream objektum soha nem lesz bezárva. A CA2000 ebben az esetben a szabály megsértését jelöli.using (StreamReader sr = new StreamReader(new FileStream("C:/myfile.txt", FileMode.Create))) { ... }A dinamikus objektumoknak árnyékobjektumot kell használniuk az IDisposable eldobási minta megvalósításához.
Mikor kell letiltani a figyelmeztetéseket?
Ne nyomja el a szabály figyelmeztetését, kivéve, ha:
- Olyan metódust hívott meg az objektumon, amely meghívja a(z)
Dispose, például a(z) Close. - A figyelmeztetést generáló metódus egy IDisposable objektumot ad vissza, amely becsomagolja az objektumot.
- Az allokálási módszer nem biztosít felszabadítási tulajdonjogot; azaz az objektum felszabadításának felelőssége egy másik, a metódusban létrehozott és a hívónak visszaadott objektumra vagy burkolóra száll át.
Figyelmeztetés mellőzése
Ha csak egyetlen szabálysértést szeretne letiltani, adjon hozzá előfeldolgozási irányelveket a forrásfájlhoz a szabály letiltásához és újbóli engedélyezéséhez.
#pragma warning disable CA2000
// The code that's violating the rule is on this line.
#pragma warning restore CA2000
Ha le szeretné tiltani egy fájl, mappa vagy projekt szabályát, állítsa annak súlyosságát none a konfigurációs fájlban.
[*.{cs,vb}]
dotnet_diagnostic.CA2000.severity = none
További információ: Kódelemzési figyelmeztetések letiltása.
Kód konfigurálása elemzéshez
Az alábbi beállításokkal konfigurálhatja, hogy a kódbázis mely részein futtassa ezt a szabályt, és mikor kell átadni a tulajdonjogot.
- Adott szimbólumok kizárása
- Adott típusok és származtatott típusok kizárása
- Tulajdonjog-átruházási konfigurálása
Emellett a következő, adatfolyam-elemzéssel kapcsolatos lehetőségek is érvényesek erre a szabályra:
- elemzési_típus_eltávolítása
- interprocedurális_elemzés_típusa
- max_interproceduralis_lambda_vagy_helyi_függvény_hívási_lánc
- max_interprocedural_method_call_chain
- mutat_elemzesi_tipusra
- copy_analysis
- megfelelő_IterációSzám_a_gyenge_KDF_algoritmushoz
Ezeket a beállításokat konfigurálhatja csak erre a szabályra, az összes szabályra, vagy az ebben a kategóriában szereplő összes szabályra (Megbízhatósági), amelyekre vonatkoznak. További információ: Kódminőségi szabály konfigurációs beállításai.
Adott szimbólumok kizárása
A excluded_symbol_names beállítással kizárhat bizonyos szimbólumokat, például típusokat és metódusokat az elemzésből. Ha például meg szeretné adni, hogy a szabály ne fusson a nevesített MyTypetípusok egyikén sem, adja hozzá a következő kulcs-érték párot a projekt egyik .editorconfig fájljához:
dotnet_code_quality.CAXXXX.excluded_symbol_names = MyType
Jegyzet
Cserélje le a XXXXCAXXXX részét a vonatkozó szabály azonosítójára.
Engedélyezett szimbólumnévformátumok a beállításértékben (a következővel |elválasztva):
- Csak szimbólumnév (a névvel ellátott összes szimbólumot tartalmazza, függetlenül attól, hogy milyen típusú vagy névtérrel rendelkezik).
- A szimbólum "dokumentációazonosító formátumában" szereplő teljes nevek. Minden szimbólumnévhez szimbólum típusú előtag szükséges, például
M:metódusokhoz,T:típusokhoz ésN:névterekhez. -
.ctorkonstruktorok és.cctorstatikus konstruktorok számára.
Példák:
| Beállítás értéke | Összegzés |
|---|---|
dotnet_code_quality.CAXXXX.excluded_symbol_names = MyType |
Megegyezik az összes elnevezett MyTypeszimbólummal. |
dotnet_code_quality.CAXXXX.excluded_symbol_names = MyType1|MyType2 |
Az összes MyType1 vagy MyType2 nevű szimbólummal megegyezik. |
dotnet_code_quality.CAXXXX.excluded_symbol_names = M:NS.MyType.MyMethod(ParamType) |
Megfelel a megadott metódusnak MyMethod a megadott teljes jogosultsággal rendelkező aláírással. |
dotnet_code_quality.CAXXXX.excluded_symbol_names = M:NS1.MyType1.MyMethod1(ParamType)|M:NS2.MyType2.MyMethod2(ParamType) |
Összepárosítja az adott metódusokat MyMethod1 és MyMethod2 a megfelelő teljesen minősített aláírásokkal. |
Adott típusok és származtatott típusok kizárása
A excluded_type_names_with_derived_types beállítás beállításával kizárhat bizonyos típusokat és azok származtatott típusait az elemzésből. Ha például meg szeretné adni, hogy a szabály ne fusson a nevesített MyType és származtatott típusok egyik metódusán sem, adja hozzá a következő kulcs-érték párot a projekt egyik .editorconfig fájljához:
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = MyType
Jegyzet
Cserélje le a XXXXCAXXXX részét a vonatkozó szabály azonosítójára.
Engedélyezett szimbólumnévformátumok a beállításértékben (a következővel |elválasztva):
- Csak típusnév (a névvel rendelkező összes típust tartalmazza, függetlenül attól, hogy milyen típust vagy névteret tartalmaz).
- A szimbólum dokumentációazonosító formátumában található teljesen minősített nevek, opcionális
T:előtaggal.
Példák:
| Beállítás értéke | Összegzés |
|---|---|
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = MyType |
Megfelel az összes névvel ellátott MyType típusnak és az összes származtatott típusnak. |
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = MyType1|MyType2 |
Megfelel minden olyan típusnak, amelyik vagy a MyType1 vagy a MyType2 nevet viseli, és az összes belőlük származtatott típusnak. |
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = M:NS.MyType |
Az adott MyType típust egyezteti a megadott teljes névvel és az összes származtatott típusával. |
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = M:NS1.MyType1|M:NS2.MyType2 |
Az MyType1 és MyType2 konkrét típusokat és azoknak a teljes kvalifikált neveket, valamint az összes származtatott típust egyezteti. |
Tulajdonjog-átruházás konfigurálása
A dispose_ownership_transfer_at_constructor és a dispose_ownership_transfer_at_method_call opciók a rendelkezési jog átruházását konfigurálják.
Ha például meg szeretné adni, hogy a szabályátadások a konstruktoroknak átadott argumentumok tulajdonjogát adják át, adja hozzá a következő kulcs-érték párot egy .editorconfig fájlhoz a projektben:
dotnet_code_quality.CAXXXX.dispose_ownership_transfer_at_constructor = true
Jegyzet
Cserélje le a XXXXCAXXXX részét a vonatkozó szabály azonosítójára.
tulajdonjog_átadás_konstruktorban
Tekintse meg a következő kód példáját.
class A : IDisposable
{
public void Dispose() { }
}
class Test
{
DisposableOwnerType M1()
{
return new DisposableOwnerType(new A());
}
}
- Ha
dotnet_code_quality.dispose_ownership_transfer_at_constructortrueértékre van állítva, a rendszer anew A()lefoglalás tulajdonjogát a visszaadottDisposableOwnerTypepéldányra továbbítja. - Ha
dotnet_code_quality.dispose_ownership_transfer_at_constructorfalsevan beállítva,Test.M1()rendelkezik anew A()kezelésének jogával, ésCA2000szabálytalanságot eredményez egy erőforrás-szivárgás miatt.
tulajdon_átadás_megsemmisítés_metódushíváskor
Tekintse meg a következő kód példáját.
class Test
{
void M1()
{
TransferDisposeOwnership(new A());
}
}
- Ha
dotnet_code_quality.dispose_ownership_transfer_at_method_calltrueértékre van állítva, anew A()lefoglalás tulajdonjogának átruházása aTransferDisposeOwnershipmetódusba történik. - Ha
dotnet_code_quality.dispose_ownership_transfer_at_method_callfalsevan beállítva, akkorTest.M1()rendelkezik anew A()megsemmisítési jogosultsággal, és ezCA2000jogsértést eredményez a megsemmisítési szivárgás miatt.
Kapcsolódó szabályok
1. példa
Ha olyan metódust implementál, amely felszabadítható objektumot ad vissza, használjon egy try/finally blokkot fogási blokk nélkül, hogy az objektum felszabadítása biztosítva legyen. Egy try/finally blokk használatával lehetővé teszi, hogy a kivétel a hibaponthoz vezető úton keletkezzen, ezzel biztosítva, hogy az objektum megfelelően fel legyen szabadítva.
Az OpenPort1 metódusban az ISerializable objektumot, a SerialPort-ot nem sikerül megnyitni, vagy a SomeMethod hívása sikertelen lehet. A megvalósítás során CA2000 figyelmeztetés jelenik meg.
Az OpenPort2 metódusban két SerialPort-objektum deklarálva van, és null értékre van állítva:
tempPort, amely a metódusműveletek sikerességét teszteli.port, amelyet a metódus visszatérési értékéhez használnak.
A tempPort blokk egy try blokkban van létrehozva és megnyitva, és minden más szükséges munka ugyanabban try a blokkban történik. A blokk végén a megnyitott portot a port objektumhoz rendelik, és az objektum visszaadásra kerül, az tempPort objektumot pedig beállítják null értékre.
A finally blokk ellenőrzi a következő értékét tempPort: . Ha nem null értékű, a metódus egyik művelete sikertelen volt, és tempPort bezárva van, hogy meggyőződjön arról, hogy az erőforrások felszabadulnak. A visszaadott portobjektum a megnyitott SerialPort objektumot fogja tartalmazni, ha a metódus műveletei sikeresek, vagy null értékű lesz, ha egy művelet meghiúsult.
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;
}
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
2. példa
Alapértelmezés szerint a Visual Basic fordítóban minden számtani operátor ellenőrzi a túlcsordulást. Ezért bármely Visual Basic-aritmetikai művelet dobhat egy OverflowException. Ez olyan szabályok váratlan megsértéséhez vezethet, mint a CA2000. Az alábbi CreateReader1 függvény például CA2000-es szabálysértést eredményez, mert a Visual Basic fordító túlcsordulás-ellenőrzési utasítást bocsát ki az összeadáshoz, amely kivételt okozhat, amely miatt a StreamReader nem lesz megsemmisítve.
Ennek kijavításához letilthatja a Visual Basic fordító által a projektben végzett túlcsordulás-ellenőrzések kibocsátását, vagy módosíthatja a kódot az alábbi CreateReader2 függvényhez hasonlóan.
A túlcsordulás-ellenőrzések kibocsátásának letiltásához kattintson a jobb gombbal a projekt nevére Megoldáskezelő, majd válassza a Tulajdonságok lehetőséget. Válassza a Fordítás>Speciális fordítási beállítások lehetőséget, majd jelölje be az egész szám túlcsordulási ellenőrzéseinek eltávolítása.
Imports System.IO
Class CA2000
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
End Class