Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
| Özellik | Değer |
|---|---|
| Kural Kimliği | CA2000 |
| Başlık | Kapsamdan çıkmadan önce nesneleri yok edin. |
| Kategori | Güvenilirlik |
| Düzeltme bozucu ya da bozmayan olabilir | Kesintisiz |
| .NET 10'da varsayılan olarak etkin | Hayır |
| Geçerli diller | C# ve Visual Basic |
Neden
IDisposable türünde bir yerel nesne oluşturulur, ancak nesneye yapılan tüm başvurular geçerli kapsam dışına çıkmadan önce nesne imha edilmez.
Varsayılan olarak, bu kural tüm kod tabanını analiz eder, ancak bu yapılandırılabilir.
Kural açıklaması
Atılabilir bir nesnenin tüm başvuruları kapsam dışında kalmadan önce açıkça atılmazsa, atık toplayıcı nesnenin sonlandırıcısını çalıştırdığında nesne belirsiz bir zamanda atılır. Nesnenin sonlandırıcısının çalışmasını engelleyecek olağanüstü bir olay meydana gelebileceğinden, nesne açıkça yok edilmelidir.
Özel durumlar
Kural CA2000, nesne atılmasa bile aşağıdaki türlerdeki yerel nesneler için çalışmaz.
- System.IO.Stream
- System.IO.StringReader
- System.IO.TextReader
- System.IO.TextWriter
- System.Resources.IResourceReader
Bu türlerden birinin nesnesini bir yapıcı metoda geçirip bir alana atamak, yeni oluşturulmuş türe bir dispose sahiplik aktarımı olduğunu gösterir. Yani, yeni oluşturulmuş tür artık nesnenin imha edilmesinden sorumludur. Kodunuzdan bu türlerden birinin bir nesnesi bir oluşturucuya geçirildiğinde, nesneye yapılan tüm başvurular kapsamdan çıkmadan önce bile sonlandırılmasa, kural CA2000'e bir ihlal gerçekleşmez.
İhlalleri düzeltme
Bu kuralın ihlalini düzeltmek için, nesneye yapılan tüm başvurular kapsam dışında kalmadan önce nesne üzerinde Dispose çağrısını yapın.
using deyimini (Using Visual Basic'te) IDisposable uygulayan nesneleri sarmak için kullanabilirsiniz. Bu yöntemle sarmalanan nesneler, using bloğunun sonunda otomatik olarak atılır. Ancak, aşağıdaki durumlar bir using deyimle işlenmemelidir veya işlenemeyecektir:
Atılabilir bir nesne döndürmek için, nesne bir bloğun
try/finallydışındaki birusingblokta oluşturulmalıdır.Bir
usingdeyiminin yapıcısında atılabilir bir nesnenin üyeleri başlatılmamalıdır.Yalnızca bir özel durum işleyicisi tarafından korunan oluşturucular bir
usingdeyimin edinim bölümünde iç içe geçirildiğinde, dış oluşturucudaki bir hata iç içe oluşturucu tarafından oluşturulan nesnenin asla kapatılmamasına neden olabilir. Aşağıdaki örnekte, StreamReader yapıcısındaki bir hata, FileStream nesnesinin hiçbir zaman kapatılmamasına neden olabilir. CA2000, bu durumda kuralın ihlalini işaret eder.using (StreamReader sr = new StreamReader(new FileStream("C:/myfile.txt", FileMode.Create))) { ... }Dinamik nesneler, IDisposable nesnelerin bertaraf desenini uygulamak için bir gölge nesne kullanmalıdır.
Uyarıların ne zaman bastırılması gerekiyor?
Aşağıdakiler dışında bu kuraldan bir uyarıyı gizlemeyin:
- Nesnenizde, `Close` gibi `
Dispose` öğesini çağıran bir yöntem çağırdınız. - Uyarıyı tetikleyen yöntem, nesnenizi sarmalayan bir IDisposable nesne döndürür.
- Ayırma yöntemi, bertaraf etme sahipliğine sahip değildir; yani, nesneyi bertaraf etme sorumluluğu, yöntem içinde oluşturulan ve çağırana döndürülen başka bir nesneye veya sarmalayıcıya aktarılır.
Uyarıyı gizleme
Yalnızca tek bir ihlali engellemek istiyorsanız, kuralı devre dışı bırakmak ve sonra yeniden etkinleştirmek için kaynak dosyanıza ön işlemci yönergeleri ekleyin.
#pragma warning disable CA2000
// The code that's violating the rule is on this line.
#pragma warning restore CA2000
Bir dosya, klasör veya projenin kuralını devre dışı bırakmak için, yapılandırma dosyasındaki önem derecesini noneolarak ayarlayın.
[*.{cs,vb}]
dotnet_diagnostic.CA2000.severity = none
Daha fazla bilgi için bkz . Kod analizi uyarılarını gizleme.
Kod çözümleme için konfigüre et
Kod tabanınızın hangi bölümlerinde bu kuralın çalıştırılacağını ve kullanım hakkı devrinin ne zaman yapılacağını yapılandırmak için aşağıdaki seçenekleri kullanın.
- Belirli simgeleri hariç tutma
- Belirli türleri ve türetilmiş türlerini dışlama
- Dispose sahiplik aktarımını yapılandırma
Ayrıca, bu kural için aşağıdaki diğer veri akışı analiziyle ilgili seçenekler geçerlidir:
- analiz_türü_elden_çıkarma
- interprocedural_analysis_kind
- max_interprocedural_lambda_or_local_function_call_chain
- max_interprocedural_method_call_chain
- points_to_analysis_kind
- copy_analysis
- zayıf KDF algoritması için yeterli İterasyon Sayısı
Bu seçenekleri yalnızca bu kural, uyguladıkları tüm kurallar veya bu kategorideki tüm kurallar için (Güvenilirlik) yapılandırabilirsiniz. Daha fazla bilgi için bkz . Kod kalitesi kuralı yapılandırma seçenekleri.
Belirli simgeleri hariç tutma
excluded_symbol_names seçeneğini ayarlayarak türler ve yöntemler gibi belirli simgeleri analizden hariç tutabilirsiniz. Örneğin, kuralın adlı MyTypetürlerdeki herhangi bir kodda çalışmaması gerektiğini belirtmek için, projenizdeki bir .editorconfig dosyasına aşağıdaki anahtar-değer çiftini ekleyin:
dotnet_code_quality.CAXXXX.excluded_symbol_names = MyType
Not
XXXX
CAXXXX bölümünü geçerli kuralın kimliğiyle değiştirin.
Seçenek değerinde izin verilen simge adı biçimleri (ile |ayrılmış):
- Yalnızca sembol adı (içerildiği tür veya ad alanından bağımsız olarak ada sahip tüm simgeleri içerir).
- Simgelerin dökümantasyon kimliği formatındaki tam adlar. Her sembol adı için, yöntemler için
M:, türler içinT:, ve ad alanları içinN:gibi bir sembol türü ön eki gerekir. -
.ctoroluşturucular ve.cctorstatik oluşturucular için.
Örnekler:
| Seçenek Değeri | Özet |
|---|---|
dotnet_code_quality.CAXXXX.excluded_symbol_names = MyType |
adlı MyTypetüm simgelerle eşleşir. |
dotnet_code_quality.CAXXXX.excluded_symbol_names = MyType1|MyType2 |
MyType1 veya MyType2 adlı tüm simgelerle eşleşir. |
dotnet_code_quality.CAXXXX.excluded_symbol_names = M:NS.MyType.MyMethod(ParamType) |
Belirtilen tam imza ile belirli bir yöntemi MyMethod eşleştirir. |
dotnet_code_quality.CAXXXX.excluded_symbol_names = M:NS1.MyType1.MyMethod1(ParamType)|M:NS2.MyType2.MyMethod2(ParamType) |
Belirli yöntemlerle MyMethod1 ve MyMethod2 ilgili tam imzalarla eşleşir. |
Belirli türleri ve türetilmiş türlerini dışlama
excluded_type_names_with_derived_types seçeneğini ayarlayarak belirli türleri ve türetilmiş türlerini analizden dışlayabilirsiniz. Örneğin, kuralın adlı MyType ve türetilmiş türleri içindeki hiçbir yöntemde çalışmaması gerektiğini belirtmek için, projenizdeki bir .editorconfig dosyasına aşağıdaki anahtar-değer çiftini ekleyin:
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = MyType
Not
XXXX
CAXXXX bölümünü geçerli kuralın kimliğiyle değiştirin.
Seçenek değerinde izin verilen simge adı biçimleri (ile |ayrılmış):
- Yalnızca tür adı (içeren tür veya ad alanına bakılmaksızın adı olan tüm türleri içerir).
- Simgenin belge kimliği biçiminde, isteğe bağlı
T:ön ek içeren tam adlar.
Örnekler:
| Seçenek değeri | Özet |
|---|---|
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = MyType |
Adı MyType olan tüm türleri ve türevlerini eşleştirir. |
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = MyType1|MyType2 |
MyType1 veya MyType2 adlı tüm türleri ve bunların türetilmiş türlerinin tamamını eşleştirir. |
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = M:NS.MyType |
Belirli bir türü MyType verilen tam adla ve türetilmiş tüm türleriyle eşleştirir. |
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = M:NS1.MyType1|M:NS2.MyType2 |
Belirli türler MyType1 ve MyType2 ile bunların türetilmiş tüm türleri, ilgili tam adlarla eşleşir. |
Sahiplik transferini yapılandırma ve sonlandırma
dispose_ownership_transfer_at_constructor ve dispose_ownership_transfer_at_method_call seçenekleri, dispose sahipliğinin aktarımını yapılandırır.
Örneğin, kuralın oluşturuculara geçirilen bağımsız değişkenlerin dispose sahipliğini aktardığını belirtmek için projenizdeki bir .editorconfig dosyasına aşağıdaki anahtar-değer çiftini ekleyin:
dotnet_code_quality.CAXXXX.dispose_ownership_transfer_at_constructor = true
Not
XXXX
CAXXXX bölümünü geçerli kuralın kimliğiyle değiştirin.
Kurucu İşlevinde Sahiplik Devri Ayarını Yapma
Aşağıdaki kod örneğini göz önünde bulundurun.
class A : IDisposable
{
public void Dispose() { }
}
class Test
{
DisposableOwnerType M1()
{
return new DisposableOwnerType(new A());
}
}
-
dotnet_code_quality.dispose_ownership_transfer_at_constructortrueolarak ayarlandığında,new A()tahsisatının sahipliği, döndürülenDisposableOwnerTypeörneğine aktarılır. -
dotnet_code_quality.dispose_ownership_transfer_at_constructorfalseolarak ayarlanırsa,Test.M1()new A()için bertaraf sahipliğini alır ve bu, bir atık sızıntısı içinCA2000ihlali oluşturur.
yöntem çağrısında sahiplik aktarımı yok et
Aşağıdaki kod örneğini göz önünde bulundurun.
class Test
{
void M1()
{
TransferDisposeOwnership(new A());
}
}
-
dotnet_code_quality.dispose_ownership_transfer_at_method_callolarak ayarlanırsa,new A()tahsis edilen kaynağın kontrolüTransferDisposeOwnershipyöntemine devredilir. - Eğer
dotnet_code_quality.dispose_ownership_transfer_at_method_call,falseolarak ayarlanırsa,Test.M1(),new A()için atma sahipliğine sahiptir ve atma sızıntısına yol açarakCA2000ihlaline neden olur.
İlgili kurallar
Örnek 1
Tek kullanımlık bir nesne döndüren bir yöntem uyguluyorsanız, nesnenin atıldığından emin olmak için catch bloğu olmayan bir try/finally bloğu kullanın. Try/finally bloğu kullanarak hata noktasında istisnaların tetiklenmesine izin verir ve nesnenin serbest bırakıldığından emin olursunuz.
OpenPort1 yönteminde, ISerializable nesnesi SerialPort'u açma çağrısı veya SomeMethod çağrısı başarısız olabilir. Bu uygulama üzerinde bir CA2000 uyarısı verilir.
OpenPort2 yönteminde iki SerialPort nesnesi bildirilir ve null olarak ayarlanır:
tempPort, yöntem işlemlerinin başarılı olup olmadığını test etmek için kullanılır.port, yönteminin dönüş değeri için kullanılır.
tempPort oluşturulur ve try bloğunda açılır, ve gerekli diğer tüm işler aynı try bloğunda gerçekleştirilir. Bloğun try sonunda, açılan bağlantı noktası döndürülecek port nesnesine atanır ve tempPort nesnesi null olarak ayarlanır.
finally bloğu tempPort değerini denetler. Null değilse, yöntemdeki bir işlem başarısız olmuştur ve tempPort tüm kaynakların serbest bırakıldığından emin olmak için kapatılır. Döndürülen bağlantı noktası nesnesi, yöntemin işlemleri başarılı olursa açık SerialPort nesnesini içerir veya bir işlem başarısız olursa null olur.
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
Örnek 2
Varsayılan olarak, Visual Basic derleyicisi tüm aritmetik işleçlerde taşma olup olmadığını kontrol eder. Bu nedenle, Visual Basic'teki herhangi bir aritmetik işlem bir OverflowException atabilir. Bu durum CA2000 gibi kurallarda beklenmeyen ihlallere yol açabilir. Örneğin, aşağıdaki CreateReader1 işlevi bir CA2000 ihlali oluşturur çünkü Visual Basic derleyicisi, StreamReader'ın atılmamasına neden olabilecek bir özel durum oluşturabilecek ekleme için bir taşma denetimi yönergesi yayar.
Bunu düzeltmek için, projenizdeki Visual Basic derleyicisi tarafından taşma denetimlerini işleme alma işlemini devre dışı bırakabilir veya kodunuzu aşağıda verilen CreateReader2 işlevi örneğindekine benzer şekilde değiştirebilirsiniz.
Taşma denetimlerinin oluşturulmasını devre dışı bırakmak için Çözüm Gezgini'nde proje adına sağ tıklayın ve Özellikler'i seçin. Gelişmiş Derleme Seçeneklerini Derle'yi>seçin ve ardından Tamsayı taşma denetimlerini kaldır'ı işaretleyin.
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