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 | Kapsamı kaybetmeden önce nesneleri bırakın |
| Kategori | Güvenilirlik |
| Hataya neden olan veya bozulmayan düzeltme | Hataya neden olmayan |
| .NET 10'da varsayılan olarak etkin | Hayır |
Neden
Bir türün IDisposable yerel nesnesi oluşturulur, ancak nesneye yapılan tüm başvurular kapsam dışı bırakılmadan önce nesne atılmaz.
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 atılmalıdır.
Özel durumlar
Kural CA2000, nesne atılmasa bile aşağıdaki türlerdeki yerel nesneler için tetiklenmez:
- System.IO.Stream
- System.IO.StringReader
- System.IO.TextReader
- System.IO.TextWriter
- System.Resources.IResourceReader
Bu türlerden birinin nesnesini bir oluşturucuya geçirip bir alana atamak, yeni oluşturulan türe bir atma sahiplik aktarımını gösterir. Yani, yeni yapılan tür artık nesnenin atılmasından sorumludur. Kodunuz bu türlerden birinin nesnesini bir oluşturucuya geçirirse, nesneye yapılan tüm başvurular kapsam dışı bırakılmadan önce atılmasa bile kural CA2000 ihlali gerçekleşmez.
İhlalleri düzeltme
Bu kuralın ihlalini düzeltmek için, nesneye yapılan tüm başvurular kapsam dışında olmadan önce nesneyi çağırın Dispose .
deyimini using (UsingVisual Basic'te) kullanarak uygulayan IDisposablenesneleri sarmalayabilirsiniz. Bu şekilde sarmalanan nesneler bloğun using 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 deyiminin oluşturucusunda atılabilir bir nesnenin üyelerini
usingbaşlatmayın.Yalnızca bir özel durum işleyicisi tarafından korunan oluşturucular bir
usingdeyimin alma bölümünde iç içe geçirildiğinde, dış oluşturucuda bir hata iç içe oluşturucu tarafından oluşturulan nesnenin hiçbir zaman kapatılmamasına neden olabilir. Aşağıdaki örnekte, oluşturucudaki StreamReader bir hata nesnenin FileStream 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, nesnelerin atma desenini IDisposable 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 gibi öğesini çağıran
DisposeClosebir yöntem çağırdınız. - Uyarıyı tetikleyen yöntem, nesnenizi sarmalayan bir IDisposable nesne döndürür.
- Ayırma yönteminin dispose sahipliği yoktur; diğer bir ifadeyle, nesneyi atma sorumluluğu yönteminde 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.
Çözümlemek için kod yapılandırma
Bu kuralın kod tabanınızın hangi bölümlerinde çalıştırılacağı ve atma sahipliğinin ne zaman aktarılacağı 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:
- dispose_analysis_kind
- interprocedural_analysis_kind
- max_interprocedural_lambda_or_local_function_call_chain
- max_interprocedural_method_call_chain
- points_to_analysis_kind
- copy_analysis
- sufficient_IterationCount_for_weak_KDF_algorithm
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çeren tür veya ad alanı ne olursa olsun, ada sahip tüm simgeleri içerir).
- Simgenin belge kimliği biçimindeki tam adlar. Her simge adı için yöntemler
M:, türler veT:ad alanları gibiN: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 |
veya MyType1adlı MyType2 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 |
Adlı MyType tüm türleri ve türetilmiş türlerinin tümünü eşleştirir. |
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = MyType1|MyType2 |
veya MyType1 adlı MyType2 tüm türleri ve türetilmiş türlerinin tümü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ürleri MyType1 ve MyType2 ilgili tam adlarla ve bunların türetilmiş tüm türleriyle eşleşir. |
Dispose sahiplik aktarımını yapılandırma
dispose_ownership_transfer_at_constructor ve dispose_ownership_transfer_at_method_call seçenekleri, dispose sahipliğinin aktarımını yapılandırılı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.
dispose_ownership_transfer_at_constructor
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 ayarlanırsa,new A()ayırmanın sahipliğini atın, döndürülenDisposableOwnerTypeörneğine aktarılır. -
dotnet_code_quality.dispose_ownership_transfer_at_constructorfalseolarak ayarlanırsaTest.M1()new A()için atma sahipliğini alır ve atma sızıntısı içinCA2000ihlaline neden olur.
dispose_ownership_transfer_at_method_call
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_calltrueolarak ayarlanırsa,new A()ayırmanın sahipliğini atTransferDisposeOwnershipyöntemine aktarılır. -
dotnet_code_quality.dispose_ownership_transfer_at_method_callfalseolarak ayarlanırsaTest.M1()new A()için atma sahipliğini alır ve atma sızıntısı içinCA2000ihlaline 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 özel durumların tetiklenmesine izin verir ve nesnenin atı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ı oluşturulur.
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 bir blokta try oluşturulur ve açılır ve gerekli diğer tüm işler aynı try blokta gerçekleştirilir. Bloğun try sonunda, açılan bağlantı noktası döndürülecek nesneye port atanır ve tempPort nesnesi olarak nullayarlanır.
blok değerini finally denetler tempPort. 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çlerin taşma denetimine sahiptir. Bu nedenle, herhangi bir Visual Basic aritmetik işlemi bir OverflowExceptionatabilir. 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 denetimlerinin yayma özelliğini devre dışı bırakabilir veya kodunuzu aşağıdaki CreateReader2 işlevinde olduğu gibi değiştirebilirsiniz.
Taşma denetimlerinin yayma özelliğini devre dışı bırakmak için, Çözüm Gezgini 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