Bagikan melalui


CA1063: Terapkan IDisposable dengan benar

Properti Nilai
ID Aturan CA1063
Judul Menerapkan IDisposable dengan benar
Golongan Desain
Perbaikan bersifat disruptif atau non-disruptif Non-disruptif
Diaktifkan secara default di .NET 8 Tidak

Penyebab

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

  • IDisposable diisi ulang di kelas .
  • Finalize ditimpa lagi.
  • Dispose() ditimpa.
  • 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, Finalize implementasi tidak memanggil atau keduanya Dispose(bool) atau finalizer kelas dasar.

Pelanggaran salah satu pola ini memicu peringatan CA1063.

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

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

Deskripsi aturan

Semua IDisposable jenis harus menerapkan pola Buang 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 jenis Anda, dan ambil alih kelas dasar Buang implementasi sebagai gantinya.

  • Hapus finalizer dari jenis Anda, ambil alih Dispose(bool disposing), dan letakkan logika finalisasi di jalur kode tempat 'membuang' salah.

  • Ambil alih Buang(pembuangan bool), dan letakkan logika buang di jalur kode tempat 'membuang' adalah benar.

  • 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), lalu memanggil pada instans SuppressFinalize objek saat ini (this, atau Me di Visual Basic), lalu kembali.

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

  • Jika Anda membuat jenis tidak tersegel yang menyatakan dan mengimplementasikan IDisposable antarmuka, 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 menekan peringatan positif palsu. Positif palsu disebabkan oleh perubahan yang melanggar dalam pengkompilasi 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 mana dari basis kode yang akan menjalankan aturan ini, berdasarkan aksesibilitasnya. 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

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);
    }
}

Baca juga