Praktik Terbaik dalam menggunakan Buang dan Selesaikan di .Net

Microsoft .Net Framework menyediakan pengumpul sampah yang berjalan di latar belakang dan melepaskan memori yang ditempati oleh objek yang dikelola ketika tidak lagi dirujuk dalam kode Anda. Meskipun pengumpul sampah mahir dalam membersihkan memori yang ditempati oleh objek yang dikelola, tidak ada jaminan bahwa memori yang ditempati oleh objek yang tidak dikelola akan dibersihkan saat siklus GC berikutnya dijalankan. Jika Anda memiliki sumber daya yang tidak dikelola dalam aplikasi Anda, Anda harus memastikan bahwa Anda melepaskan sumber daya tersebut secara eksplisit setelah selesai menggunakannya. Dalam artikel ini, saya akan menyoroti praktik terbaik yang harus Anda ikuti untuk membersihkan sumber daya yang digunakan dalam aplikasi Anda.

GC menggunakan generasi untuk memelihara dan mengelola umur relatif objek yang dibuat dalam memori. Objek yang baru dibuat ditempatkan pada generasi 0. Asumsi dasarnya adalah objek yang baru dibuat mungkin memiliki umur pakai yang lebih pendek sedangkan objek yang sudah lama mungkin memiliki umur pakai yang lebih lama. Saat objek yang berada di generasi 0 tidak diambil kembali setelah siklus GC, mereka akan dipindahkan ke generasi 1. Demikian pula, jika objek yang berada di generasi 1 bertahan dari pembersihan GC, mereka akan dipindahkan ke generasi 2. Perhatikan bahwa GC berjalan lebih sering di generasi yang lebih rendah dari yang lebih tinggi. Jadi, objek yang berada di generasi 0 akan lebih sering dibersihkan dibandingkan dengan objek yang berada di generasi 1. Jadi,Ini adalah praktik pemrograman yang lebih baik untuk memastikan bahwa Anda menggunakan lebih banyak objek lokal daripada objek dalam cakupan yang lebih tinggi untuk menghindari objek dipindahkan ke generasi yang lebih tinggi.

Perhatikan bahwa ketika Anda memiliki destruktor di kelas Anda, runtime akan memperlakukannya sebagai metode Finalize (). Karena penyelesaian itu mahal, Anda sebaiknya hanya menggunakan destruktor jika diperlukan - ketika Anda memiliki beberapa sumber daya di kelas yang perlu Anda bersihkan. Ketika Anda memiliki finalizer di kelas Anda, objek dari kelas tersebut dipindahkan ke antrian finalisasi. Jika objek dapat dijangkau, mereka akan dipindahkan ke antrian "Freachable". GC mengambil kembali memori yang ditempati oleh objek yang tidak dapat dijangkau. Secara berkala, GC memeriksa apakah objek yang berada di antrean "Freachable" dapat dijangkau. Jika tidak dapat dijangkau, memori yang ditempati oleh objek tersebut akan diambil kembali. Jadi, jelas bahwa objek yang berada dalam antrian "Freachable" akan membutuhkan lebih banyak waktu untuk dibersihkan oleh pengumpul sampah.Merupakan praktik yang buruk untuk memiliki destruktor kosong di kelas C # Anda karena objek untuk kelas tersebut akan dipindahkan ke antrean finalisasi dan kemudian ke antrean "Dapat dilepas" jika perlu.

Finalizer secara implisit dipanggil saat memori yang ditempati oleh objek diperoleh kembali. Namun, finalisator tidak dijamin akan dipanggil oleh GC - mungkin atau mungkin tidak dipanggil sama sekali. Intinya, finalizer bekerja pada mode non-deterministik - waktu proses tidak menjamin bahwa finalizer akan dipanggil sama sekali. Namun Anda dapat memaksa finalizer dipanggil meskipun itu sama sekali bukan praktik yang baik karena ada penalti kinerja yang terkait. Finalizer harus selalu dilindungi dan harus selalu digunakan untuk membersihkan sumber daya yang dikelola saja. Anda tidak boleh mengalokasikan memori di dalam finalizer, menulis kode untuk mengimplementasikan keamanan thread atau memanggil metode virtual dari dalam finalizer.

Sebaliknya, metode Buang menyediakan pendekatan "pembersihan deterministik" terhadap pembersihan sumber daya di .Net. Bagaimanapun, metode Dispose tidak seperti finalizer yang harus dipanggil secara eksplisit. Jika Anda memiliki metode Buang yang ditentukan di kelas, Anda harus memastikan bahwa itu dipanggil. Jadi, metode Buang harus dipanggil secara eksplisit oleh kode klien. Tetapi bagaimana jika Anda lupa memanggil metode Dispose yang diekspos oleh kelas yang menggunakan sumber daya yang tidak terkelola? Klien dari sebuah instance dari kelas yang mengimplementasikan antarmuka IDisposable harus memanggil metode Dispose secara eksplisit. Dalam hal ini, Anda perlu memanggil Buang dari dalam finalizer. Strategi finalisasi deterministik otomatis ini memastikan bahwa sumber daya tidak terkelola yang digunakan dalam kode Anda dibersihkan.

Anda harus menerapkan IDisposable pada setiap jenis yang memiliki finalizer. Ini adalah praktik yang disarankan untuk mengimplementasikan Buang dan Selesaikan saat Anda memiliki sumber daya yang tidak terkelola di kelas Anda.

Potongan kode berikut menggambarkan bagaimana Anda dapat menerapkan pola Dispose Finalize di C #.

Void virtual yang dilindungi Buang (bool disposing)

        {

            jika (membuang)

            {

                // tulis kode untuk membersihkan objek yang dikelola

            }

            // tulis kode untuk membersihkan objek dan sumber daya yang tidak terkelola

        }

Metode Buang berparameter ini dapat dipanggil secara otomatis dari destruktor seperti yang ditunjukkan pada potongan kode di bawah ini.

  ~ Sumber Daya ()

        {

            jika (! dibuang)

            {

                dibuang = benar;

                Buang (salah);

            }

        }