CA1063: Terapkan IDisposable dengan benar

Properti Nilai
ID Aturan CA1063
Judul Menerapkan IDisposable dengan benar
Kategori Desain
Perbaikan bersifat merusak atau tidak merusak Tidak terputus
Diaktifkan secara default di .NET 10 Tidak
Bahasa yang berlaku C# dan Visual Basic

Penyebab

Antarmuka System.IDisposable tidak diimplementasikan dengan benar. Kemungkinan alasan untuk ini meliputi:

  • IDisposable diimplementasi ulang di kelas.
  • Finalize ditimpa lagi.
  • Dispose() digantikan.
  • Metode Dispose() ini tidak publik, disegel, atau bernama Buang.
  • Dispose(bool) tidak dilindungi, virtual, atau tidak tersegel.
  • Dalam jenis yang tidak disegel, Dispose() harus memanggil Dispose(true).
  • Untuk jenis yang tidak disegel, implementasi Finalize tidak memanggil Dispose(bool), finalizer kelas dasar, atau keduanya.

Pelanggaran salah satu pola ini memicu peringatan CA1063.

Setiap tipe yang tidak tersegel yang mendeklarasikan dan mengimplementasikan antarmuka IDisposable harus menyediakan metode protected virtual void Dispose(bool)-nya sendiri. Dispose() harus memanggil Dispose(true), dan finalizer harus memanggil Dispose(false). Jika Anda membuat jenis yang tidak tertutup yang mendeklarasikan dan mengimplementasikan antarmuka IDisposable, Anda harus menentukan Dispose(bool) dan memanggilnya. Untuk informasi selengkapnya, lihat Membersihkan sumber daya yang tidak dikelola (panduan .NET) dan Menerapkan Metode Dispose.

Secara default, aturan ini hanya melihat jenis yang terlihat secara eksternal, tetapi ini dapat dikonfigurasi.

Deskripsi aturan

Semua IDisposable jenis harus menerapkan pola Dispose dengan benar.

Cara memperbaiki pelanggaran

Periksa kode Anda dan tentukan resolusi mana yang akan memperbaiki pelanggaran ini:

  • Hapus IDisposable dari daftar antarmuka yang diimplementasikan oleh tipe Anda, dan override implementasi Dispose dari kelas dasar sebagai gantinya.

  • Hapus finalizer dari tipe Anda, override Dispose(bool disposing), dan letakkan logika finalisasi di jalur kode di mana 'disposing' bernilai false.

  • Override Dispose(bool disposing), dan letakkan logika disposesi di jalur kode di mana 'disposing' bernilai true.

  • Pastikan Bahwa Dispose() dinyatakan sebagai publik dan disegel.

  • Ganti nama metode pembuangan Anda menjadi Buang dan pastikan metode tersebut dinyatakan sebagai publik dan disegel.

  • Pastikan Bahwa Dispose(bool) dinyatakan sebagai dilindungi, virtual, dan tidak tersegel.

  • Ubah Dispose() sehingga memanggil Dispose(true), kemudian memanggil metode SuppressFinalize pada instans objek saat ini (this, atau Me di Visual Basic), kemudian mengembalikan.

  • Ubah finalizer Anda sehingga memanggil Dispose(false) lalu kembali.

  • Jika Anda membuat jenis yang tidak tersegel yang menyatakan dan mengimplementasikan antarmuka IDisposable, pastikan bahwa implementasi IDisposable mengikuti pola yang dijelaskan sebelumnya di bagian ini.

Kapan harus menekan peringatan

Jangan menyembunyikan peringatan dari aturan ini.

Catatan

Anda mungkin melihat peringatan positif palsu dari aturan ini jika semua hal berikut ini berlaku:

  • Anda menggunakan Visual Studio 2022 versi 17.5 atau yang lebih baru dengan versi .NET SDK yang lebih lama, yaitu, .NET 6 atau yang lebih lama.
  • Anda menggunakan penganalisis dari .NET 6 SDK atau versi paket penganalisis yang lebih lama, seperti Microsoft.CodeAnalysis.FxCopAnalyzers.
  • Anda memiliki atribut pada implementasi Anda IDispose .

Dalam hal ini, aman untuk mengabaikan peringatan positif palsu. Positif palsu disebabkan oleh perubahan besar dalam kompiler C#. Pertimbangkan untuk menggunakan penganalisis yang lebih baru yang berisi perbaikan untuk peringatan positif palsu. Tingkatkan ke Microsoft.CodeAnalysis.NetAnalyzers versi 7.0.0-preview1.22464.1 atau yang lebih baru atau gunakan penganalisis dari .NET 7 SDK.

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 (Desain) yang berlaku untuk aturan ini. Untuk informasi selengkapnya, lihat Opsi konfigurasi aturan kualitas kode.

Menyertakan permukaan API tertentu

Anda dapat mengonfigurasi bagian basis kode mana yang akan dijalankan aturan ini, berdasarkan aksesibilitasnya, dengan mengatur opsi api_surface. Misalnya, untuk menentukan bahwa aturan hanya boleh dijalankan pada permukaan API non-publik, tambahkan pasangan kunci-nilai berikut ke file .editorconfig di proyek Anda:

dotnet_code_quality.CAXXXX.api_surface = private, internal

Catatan

Ganti bagian XXXXCAXXXX dengan ID aturan yang berlaku.

Contoh kode semu

Kode semu berikut memberikan contoh umum tentang bagaimana Dispose(bool) harus diimplementasikan di kelas yang menggunakan sumber daya terkelola dan asli.

public class Resource : IDisposable
{
    private bool isDisposed;
    private IntPtr nativeResource = Marshal.AllocHGlobal(100);
    private AnotherResource managedResource = new AnotherResource();

    // Dispose() calls Dispose(true)
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    // The bulk of the clean-up code is implemented in Dispose(bool)
    protected virtual void Dispose(bool disposing)
    {
        if (isDisposed) return;

        if (disposing)
        {
            // free managed resources
            managedResource.Dispose();
        }

        // free native resources if there are any.
        if (nativeResource != IntPtr.Zero)
        {
            Marshal.FreeHGlobal(nativeResource);
            nativeResource = IntPtr.Zero;
        }

        isDisposed = true;
    }

    // NOTE: Leave out the finalizer altogether if this class doesn't
    // own unmanaged resources, but leave the other methods
    // exactly as they are.
    ~Resource()
    {
        // Finalizer calls Dispose(false)
        Dispose(false);
    }
}

Lihat juga