Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
| Properti | Nilai |
|---|---|
| ID Aturan | CA2000 |
| Judul | Hentikan objek sebelum kehilangan lingkup |
| Kategori | Keandalan |
| Perbaikan bersifat merusak atau tidak merusak | Tidak terputus |
| Diaktifkan secara default di .NET 10 | Tidak |
| Bahasa yang berlaku | C# dan Visual Basic |
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 terhadapnya keluar dari cakupan, objek akan dibuang pada waktu yang tidak ditentukan ketika garbage collector menjalankan finalizer dari objek tersebut. 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 ini, meskipun objek tersebut tidak dihapus:
- System.IO.Stream
- System.IO.StringReader
- System.IO.TextReader
- System.IO.TextWriter
- System.Resources.IResourceReader
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 menghapus objek. Jika kode Anda meneruskan objek dari tipe ini ke konstruktor, tidak ada pelanggaran aturan CA2000 yang terjadi bahkan jika objek tidak dibuang sebelum semua referensi terhadapnya tidak lagi dalam jangkauan.
Cara memperbaiki pelanggaran
Untuk memperbaiki pelanggaran aturan ini, panggil Dispose pada objek sebelum semua referensinya keluar dari 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/finallydi luar blokusing.Jangan menginisialisasi anggota objek sekali pakai dalam konstruktor pernyataan
using.Ketika konstruktor yang hanya dilindungi oleh satu pengecualian handler bersarang dalam bagian akuisisi pernyataan
using, kegagalan di konstruktor luar dapat mengakibatkan objek yang dibuat oleh konstruktor yang bersarang tidak pernah ditutup dengan benar. Dalam contoh berikut, kegagalan dalam konstruktor StreamReader dapat mengakibatkan objek FileStream tidak pernah ditutup. CA2000 menandai 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 dispose pattern dari 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 dari basis kode Anda yang akan dijalankan oleh aturan ini, dan kapan kepemilikan sumber daya harus diserahkan.
- Mengecualikan simbol tertentu
- Mengecualikan jenis tertentu dan jenis turunannya
- Mengonfigurasi transfer kepemilikan pelepasan
Selain itu, opsi terkait analisis aliran data lainnya berikut berlaku untuk aturan ini:
- dispose_analysis_kind
- jenis_analisis_antarprosedural
- max_interprocedural_lambda_or_local_function_call_chain
- rantai_panggilan_metode_interprosedural_maksimum
- points_to_analysis_kind
- copy_analysis
- JumlahIterasi_Cukup_untuk_algoritma_KDF_lemah
Anda dapat mengonfigurasi opsi ini hanya untuk aturan ini, untuk semua aturan yang berlaku, atau untuk semua aturan dalam kategori ini (Keandalan) yang berlaku. Untuk informasi selengkapnya, lihat Opsi konfigurasi aturan kualitas kode.
Mengecualikan simbol tertentu
Anda dapat mengecualikan simbol tertentu, seperti jenis dan metode, dari analisis dengan mengatur opsi excluded_symbol_names. 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
Nota
Ganti bagian XXXXCAXXXX dengan ID aturan yang berlaku.
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, danN:untuk namespace. -
.ctoruntuk konstruktor dan.cctoruntuk 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 metode tertentu MyMethod dengan tanda tangan memenuhi syarat penuh yang ditentukan. |
dotnet_code_quality.CAXXXX.excluded_symbol_names = M:NS1.MyType1.MyMethod1(ParamType)|M:NS2.MyType2.MyMethod2(ParamType) |
Mencocokkan metode tertentu MyMethod1 dan MyMethod2 dengan tanda tangan lengkap masing-masing. |
Mengecualikan jenis tertentu dan jenis turunannya
Anda dapat mengecualikan jenis tertentu dan jenis turunannya dari analisis dengan mengatur opsi excluded_type_names_with_derived_types. 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
Nota
Ganti bagian XXXXCAXXXX dengan ID aturan yang berlaku.
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 dikualifikasi dalam format ID dokumentasi simbol, dengan awalan
T:yang bersifat 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 jenis tertentu MyType dengan nama lengkap yang diberikan dan semua jenis turunannya. |
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = M:NS1.MyType1|M:NS2.MyType2 |
Mencocokkan jenis tertentu MyType1 dan MyType2 dengan nama lengkap yang memenuhi syarat, serta semua jenis turunannya. |
Mengonfigurasi transfer kepemilikan pelepasan
Opsi dispose_ownership_transfer_at_constructor dan dispose_ownership_transfer_at_method_call mengonfigurasi transfer kepemilikan pembuangan.
Misalnya, untuk menentukan bahwa aturan mentransfer kepemilikan buang untuk argumen yang diteruskan ke konstruktor, tambahkan pasangan kunci-nilai berikut ke file .editorconfig di proyek Anda:
dotnet_code_quality.CAXXXX.dispose_ownership_transfer_at_constructor = true
Nota
Ganti bagian XXXXCAXXXX dengan ID aturan yang berlaku.
pemindahan_kepemilikan_pada_konstruktor
Pertimbangkan contoh kode berikut.
class A : IDisposable
{
public void Dispose() { }
}
class Test
{
DisposableOwnerType M1()
{
return new DisposableOwnerType(new A());
}
}
- Jika
dotnet_code_quality.dispose_ownership_transfer_at_constructordiatur ketrue, kepemilikan untuk alokasinew A()dipindahkan ke instansDisposableOwnerTypeyang dikembalikan. - Jika
dotnet_code_quality.dispose_ownership_transfer_at_constructordiatur kefalse,Test.M1()memiliki kepemilikan pelepasan untuknew A(), dan mengakibatkan pelanggaranCA2000karena kebocoran pelepasan.
hapus_transfer_kepemilikan_selama_panggilan_metode
Pertimbangkan contoh kode berikut.
class Test
{
void M1()
{
TransferDisposeOwnership(new A());
}
}
- Jika
dotnet_code_quality.dispose_ownership_transfer_at_method_calldiatur ketrue, buang kepemilikan untuk alokasinew A()ditransfer ke metodeTransferDisposeOwnership. - Jika
dotnet_code_quality.dispose_ownership_transfer_at_method_calldiatur kefalse,Test.M1()menangani penghapusan untuknew A(), dan menghasilkan pelanggaranCA2000untuk kebocoran pembuangan.
Aturan terkait
Contoh 1
Jika Anda menerapkan metode yang mengembalikan objek sekali pakai, gunakan blok try/finally tanpa blok catch untuk memastikan bahwa objek tersebut dihapus. 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 sebagai nilai pengembalian dari 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 nilai bukan null, berarti operasi dalam metode telah gagal, dan tempPort ditutup untuk memastikan bahwa semua sumber daya dibebaskan. 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 mengatur semua operator aritmatika untuk memeriksa overflow. 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 menghasilkan instruksi pemeriksaan overflow untuk penambahan yang dapat melempar pengecualian, yang dapat mengakibatkan StreamReader tidak di-dispose.
Untuk memperbaikinya, Anda dapat menonaktifkan pemeriksaan overflow oleh pengompilasi Visual Basic dalam proyek Anda atau Anda dapat memodifikasi kode Anda seperti pada fungsi CreateReader2 berikut.
Untuk mematikan pengaktifan pemeriksaan overflow, 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