Bagikan melalui


CA2000: Membuang objek sebelum kehilangan cakupan

Properti Nilai
ID Aturan CA2000
Judul Buang objek sebelum kehilangan cakupan
Golongan Keandalan
Perbaikan bersifat disruptif atau non-disruptif Non-disruptif
Diaktifkan secara default di .NET 8 No

Penyebab

Objek lokal dari jenis IDisposable dibuat, tetapi objek tidak dibuang sebelum semua referensi ke objek berada di luar cakupan.

Secara default, aturan ini menganalisis seluruh codebase, tetapi ini dapat dikonfigurasi.

Deskripsi aturan

Jika objek sekali pakai tidak dibuang secara eksplisit sebelum semua referensi ke dalamnya berada di luar cakupan, objek akan dibuang pada beberapa waktu yang tidak ditentukan ketika pengumpul sampah menjalankan finalizer objek. Karena mungkin terjadi peristiwa luar biasa yang akan mencegah finalizer objek berjalan, objek harus dibuang secara eksplisit sebagai gantinya.

Kasus khusus

Aturan CA2000 tidak diaktifkan untuk objek lokal dari jenis berikut meskipun objek tidak dibuang:

Meneruskan objek dari salah satu jenis ini ke konstruktor lalu menetapkannya ke bidang menunjukkan transfer kepemilikan buang ke jenis yang baru dibangun. Artinya, jenis yang baru dibangun sekarang bertanggung jawab untuk membuang objek. Jika kode Anda meneruskan objek dari salah satu jenis ini ke konstruktor, tidak ada pelanggaran aturan CA2000 yang terjadi bahkan jika objek tidak dibuang sebelum semua referensi ke dalamnya berada di luar cakupan.

Cara memperbaiki pelanggaran

Untuk memperbaiki pelanggaran aturan ini, panggil Dispose pada objek sebelum semua referensi ke dalamnya berada di luar cakupan.

Anda dapat menggunakan using pernyataan (Using dalam Visual Basic) untuk membungkus objek yang mengimplementasikan IDisposable. Objek yang dibungkus dengan cara ini secara otomatis dibuang di akhir blok using. Namun, situasi berikut tidak boleh atau tidak dapat ditangani dengan pernyataan using:

  • Untuk mengembalikan objek sekali pakai, objek harus dibangun di blok try/finally di luar blok using.

  • Jangan menginisialisasi anggota objek sekali pakai dalam konstruktor pernyataan using.

  • Ketika konstruktor yang dilindungi oleh hanya satu handler pengecualian disarangkan di bagian akuisisi pernyataan using, kegagalan di konstruktor luar dapat mengakibatkan objek yang dibuat oleh konstruktor bersarang tidak pernah ditutup. Dalam contoh berikut, kegagalan dalam konstruktor StreamReader dapat mengakibatkan objek FileStream tidak pernah ditutup. CA2000 memberi bendera pelanggaran aturan dalam kasus ini.

    using (StreamReader sr = new StreamReader(new FileStream("C:/myfile.txt", FileMode.Create)))
    { ... }
    
  • Objek dinamis harus menggunakan objek bayangan untuk mengimplementasikan pola pembuangan objek IDisposable.

Kapan harus menekan peringatan

Jangan menyembunyikan peringatan dari aturan ini kecuali jika:

  • Anda telah memanggil metode pada objek Anda yang memanggil Dispose, seperti Close.
  • Metode yang memunculkan peringatan mengembalikan objek IDisposable yang membungkus objek Anda.
  • Metode alokasi tidak memiliki kepemilikan pembuangan; yaitu, tanggung jawab untuk membuang objek ditransfer ke objek atau pembungkus lain yang dibuat dalam metode dan dikembalikan ke pemanggil.

Menyembunyikan peringatan

Jika Anda hanya ingin menyembunyikan satu pelanggaran, tambahkan arahan praprosedur ke file sumber Anda untuk dinonaktifkan lalu aktifkan kembali aturannya.

#pragma warning disable CA2000
// The code that's violating the rule is on this line.
#pragma warning restore CA2000

Untuk menonaktifkan aturan untuk file, folder, atau proyek, atur tingkat keparahannya ke none dalam file konfigurasi.

[*.{cs,vb}]
dotnet_diagnostic.CA2000.severity = none

Untuk informasi selengkapnya, lihat Cara menyembunyikan peringatan analisis kode.

Mengonfigurasi kode yang akan dianalisis

Gunakan opsi berikut untuk mengonfigurasi bagian mana dari codebase Anda yang akan menjalankan aturan ini.

Anda dapat mengonfigurasi opsi ini hanya untuk aturan ini, untuk semua aturan yang berlaku untuknya, atau untuk semua aturan dalam kategori ini (Keandalan) yang diterapkannya. Untuk informasi selengkapnya, lihat Opsi konfigurasi aturan kualitas kode.

Mengecualikan simbol tertentu

Anda dapat mengecualikan simbol tertentu, seperti jenis dan metode, dari analisis. Misalnya, untuk menentukan bahwa aturan tidak boleh berjalan pada kode apa pun dalam jenis bernama MyType, tambahkan pasangan kunci-nilai berikut ke file .editorconfig di proyek Anda:

dotnet_code_quality.CAXXXX.excluded_symbol_names = MyType

Format nama simbol yang diizinkan pada nilai opsi (dipisahkan oleh |):

  • Nama simbol saja (menyertakan semua simbol dengan nama, terlepas dari jenis atau namespace yang memuatnya).
  • Nama yang sepenuhnya memenuhi syarat dalam format ID dokumentasi simbol. Setiap nama simbol memerlukan awalan jenis simbol, seperti M: untuk metode, T: untuk jenis, dan N: untuk namespace.
  • .ctor untuk konstruktor dan .cctor untuk konstruktor statik.

Contoh:

Nilai Opsi Ringkasan
dotnet_code_quality.CAXXXX.excluded_symbol_names = MyType Mencocokkan semua simbol bernama MyType.
dotnet_code_quality.CAXXXX.excluded_symbol_names = MyType1|MyType2 Mencocokkan semua simbol bernama MyType1 atau MyType2.
dotnet_code_quality.CAXXXX.excluded_symbol_names = M:NS.MyType.MyMethod(ParamType) Mencocokkan MyMethod metode tertentu dengan tanda tangan yang sepenuhnya memenuhi syarat yang ditentukan.
dotnet_code_quality.CAXXXX.excluded_symbol_names = M:NS1.MyType1.MyMethod1(ParamType)|M:NS2.MyType2.MyMethod2(ParamType) Mencocokkan MyMethod1 dan MyMethod2 metode tertentu dengan masing-masing tanda tangan yang sepenuhnya memenuhi syarat.

Mengecualikan jenis tertentu dan jenis turunannya

Anda dapat mengecualikan jenis tertentu dan jenis turunannya dari analisis. Misalnya, untuk menentukan bahwa aturan tidak boleh dijalankan pada metode apa pun dalam jenis bernama MyType dan jenis turunannya, tambahkan pasangan kunci-nilai berikut ke file .editorconfig di proyek Anda:

dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = MyType

Format nama simbol yang diizinkan pada nilai opsi (dipisahkan oleh |):

  • Nama jenis saja (mencakup semua jenis dengan nama, terlepas dari jenis atau namespace yang memuatnya).
  • Nama yang sepenuhnya memenuhi syarat dalam format ID dokumentasi simbol, dengan awalan T: opsional.

Contoh:

Nilai Opsi Ringkasan
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = MyType Mencocokkan semua jenis bernama MyType dan semua jenis turunannya.
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = MyType1|MyType2 Mencocokkan semua jenis bernama MyType1 atau MyType2 dan semua jenis turunannya.
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = M:NS.MyType Mencocokkan MyType jenis tertentu dengan nama yang sepenuhnya memenuhi syarat tertentu dan semua jenis turunannya.
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = M:NS1.MyType1|M:NS2.MyType2 Mencocokkan MyType1 dan MyType2 jenis tertentu dengan masing-masing nama yang sepenuhnya memenuhi syarat, dan semua jenis turunannya.

Contoh 1

Jika Anda menerapkan metode yang mengembalikan objek sekali pakai, gunakan blok try/finally tanpa blok tangkap untuk memastikan bahwa objek dibuang. Dengan menggunakan blok try/finally, Anda mengizinkan pengecualian untuk dimunculkan pada titik kesalahan dan memastikan bahwa objek dibuang.

Dalam metode OpenPort1, panggilan untuk membuka objek ISerializable SerialPort atau panggilan ke SomeMethod dapat gagal. Peringatan CA2000 dimunculkan pada implementasi ini.

Dalam metode OpenPort2, dua objek SerialPort dideklarasikan dan diatur ke null:

  • tempPort, yang digunakan untuk menguji bahwa operasi metode berhasil.

  • port, yang digunakan untuk nilai pengembalian metode.

tempPort dibangun dan dibuka dalam blok try, dan pekerjaan lain yang diperlukan dilakukan di blok try yang sama. Di akhir blok try, port yang dibuka ditetapkan ke objek port yang akan dikembalikan dan objek tempPort diatur ke null.

Blok finally memeriksa nilai tempPort. Jika tidak null, operasi dalam metode telah gagal, dan tempPort ditutup untuk memastikan bahwa sumber daya apa pun dirilis. Objek port yang dikembalikan akan berisi objek SerialPort yang dibuka jika operasi metode berhasil, atau akan null jika operasi gagal.

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

Contoh 2

Secara default, pengompilasi Visual Basic memiliki semua operator aritmatika yang memeriksa luapan. Oleh karena itu, setiap operasi aritmatika Visual Basic mungkin menampilkan OverflowException. Ini dapat menyebabkan pelanggaran tak terduga dalam aturan seperti CA2000. Misalnya, fungsi CreateReader1 berikut akan menghasilkan pelanggaran CA2000 karena pengompilasi Visual Basic memancarkan instruksi pemeriksaan luapan untuk penambahan yang dapat menampilkan pengecualian yang akan menyebabkan StreamReader tidak dibuang.

Untuk memperbaikinya, Anda dapat menonaktifkan pemancaran pemeriksaan luapan oleh pengompilasi Visual Basic dalam proyek Anda atau Anda dapat memodifikasi kode Anda seperti dalam fungsi CreateReader2 berikut.

Untuk menonaktifkan pemancaran pemeriksaan luapan, klik kanan nama proyek di Penjelajah Solusi lalu pilih Properti. Pilih Kompilasi>Opsi Kompilasi Tingkat Lanjut, lalu centang Hapus pemeriksaan luapan bilangan bulat.

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

Lihat juga