CA2000: Kapsamı kaybetmeden önce verileri atın
Ö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 8'de 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
(Using
Visual 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
using
dışındaki birtry/finally
blokta oluşturulmalıdır.Bir deyiminin oluşturucusunda atılabilir bir nesnenin üyelerini
using
başlatmayın.Yalnızca bir özel durum işleyicisi tarafından korunan oluşturucular bir
using
deyimin 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
Dispose
Closebir 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 none
olarak 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ılacaklarını yapılandırmak için aşağıdaki seçenekleri kullanın.
Bu seçenekleri yalnızca bu kural, geçerli olduğu tüm kurallar veya bu kategorideki (Güvenilirlik) tüm kurallar için yapılandırabilirsiniz. Daha fazla bilgi için bkz . Kod kalitesi kuralı yapılandırma seçenekleri.
Belirli simgeleri hariç tutma
Türler ve yöntemler gibi belirli simgeleri analizden hariç tutabilirsiniz. Örneğin, kuralın adlı MyType
tü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
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
T:
, türler veN:
ad alanları gibiM:
bir sembol türü ön eki gerekir. .ctor
oluşturucular ve.cctor
statik oluşturucular için.
Örnekler:
Seçenek Değeri | Özet |
---|---|
dotnet_code_quality.CAXXXX.excluded_symbol_names = MyType |
adlı MyType tüm simgelerle eşleşir. |
dotnet_code_quality.CAXXXX.excluded_symbol_names = MyType1|MyType2 |
veya MyType2 adlı MyType1 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
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
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 MyType2 adlı MyType1 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. |
İ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 null
ayarlanı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
Ayrıca bkz.
Geri Bildirim
https://aka.ms/ContentUserFeedback.
Çok yakında: 2024 boyunca, içerik için geri bildirim mekanizması olarak GitHub Sorunları’nı kullanımdan kaldıracak ve yeni bir geri bildirim sistemiyle değiştireceğiz. Daha fazla bilgi için bkz.Gönderin ve geri bildirimi görüntüleyin