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:

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 using dışındaki bir try/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 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ı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ı 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

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öntemlerT:, türler ve N: ad alanları gibi M: 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ı MyTypetüm simgelerle eşleşir.
dotnet_code_quality.CAXXXX.excluded_symbol_names = MyType1|MyType2 veya MyType2adlı 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.

Ö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

Ayrıca bkz.