Di .NET, dalam kondisi apa saya harus menggunakan GC.SuppressFinalize()
?
Apa keuntungan yang diberikan metode ini kepada saya?
Di .NET, dalam kondisi apa saya harus menggunakan GC.SuppressFinalize()
?
Apa keuntungan yang diberikan metode ini kepada saya?
Jawaban:
SuppressFinalize
seharusnya hanya dipanggil oleh kelas yang memiliki finalizer. Ini menginformasikan kepada Pengumpul Sampah (GC) bahwathis
objek telah dibersihkan sepenuhnya.IDisposable
Pola yang disarankan ketika Anda memiliki finalizer adalah:Biasanya, CLR menyimpan tab pada objek dengan finalizer ketika mereka dibuat (membuatnya lebih mahal untuk dibuat).
SuppressFinalize
memberi tahu GC bahwa objek telah dibersihkan dengan benar dan tidak perlu masuk ke antrian finalizer. Itu terlihat seperti destruktor C ++, tetapi tidak bertindak seperti itu.The
SuppressFinalize
optimasi tidak sepele, sebagai obyek Anda dapat hidup lama menunggu di antrian finalizer. Jangan tergoda untuk memanggilSuppressFinalize
benda lain, ingatlah Anda. Itu cacat serius menunggu untuk terjadi.Pedoman desain memberi tahu kami bahwa finalizer tidak diperlukan jika objek Anda diimplementasikan
IDisposable
, tetapi jika Anda memiliki finalizer, Anda harus mengimplementasikannyaIDisposable
untuk memungkinkan pembersihan deterministik kelas Anda.Sebagian besar waktu Anda harus bisa lolos
IDisposable
membersihkan sumber daya. Anda hanya perlu finalizer ketika objek Anda memegang sumber daya yang tidak dikelola dan Anda perlu memastikan sumber daya tersebut dibersihkan.Catatan: Terkadang coders akan menambahkan finalizer ke debug build dari
IDisposable
kelas mereka sendiri untuk menguji kode yang telah membuangIDisposable
objek mereka dengan benar.sumber
IDisposable
tidaksealed
, maka harus menyertakan panggilanGC.SuppressFinalize(this)
bahkan jika itu tidak termasuk finalizer yang ditentukan pengguna . Ini diperlukan untuk memastikan semantik yang tepat untuk tipe turunan yang menambahkan finalizer yang ditentukan pengguna tetapi hanya menimpaDispose(bool)
metode yang dilindungi .sealed
seperti yang disebutkan oleh @SamHarwell adalah penting, untuk kelas turunan. Hasil CodeAnalysis di ca1816 + ca1063 ketika kelas tidak disegel, tetapi kelas disegel baik-baik saja tanpaSuppressFinalize
.SupressFinalize
memberitahu sistem bahwa pekerjaan apa pun yang telah dilakukan di finalizer telah dilakukan, sehingga finalizer tidak perlu dipanggil. Dari .NET docs:Secara umum, hampir semua
Dispose()
metode harus dapat memanggilGC.SupressFinalize()
, karena itu harus membersihkan segala sesuatu yang akan dibersihkan di finalizer.SupressFinalize
hanyalah sesuatu yang menyediakan optimasi yang memungkinkan sistem untuk tidak repot mengantri objek ke thread finalizer. SeorangDispose()
finalizer yang ditulis dengan benar harus bekerja dengan baik dengan atau tanpa panggilanGC.SupressFinalize()
.sumber
Metode itu harus dipanggil pada
Dispose
metode objek yang mengimplementasikanIDisposable
, dengan cara ini GC tidak akan memanggil finalizer lain kali jika seseorang memanggilDispose
metode tersebut.Lihat: Metode GC.SuppressFinalize (Obyek) - Microsoft Documents
sumber
Jika objek memiliki finalizer, .net menaruh referensi dalam antrian finalisasi.
Karena kita memiliki panggilan
Dispose(ture)
, itu jelas objek, jadi kita tidak perlu antrian finalisasi untuk melakukan pekerjaan ini.Jadi panggilan
GC.SuppressFinalize(this)
hapus referensi dalam antrian finalisasi.sumber
Jika suatu kelas, atau sesuatu yang diturunkan darinya, mungkin memiliki referensi langsung terakhir ke objek dengan finalizer, maka salah satu
GC.SuppressFinalize(this)
atauGC.KeepAlive(this)
harus dipanggil pada objek setelah operasi apa pun yang mungkin terpengaruh oleh finalizer itu, sehingga memastikan bahwa finalizer menang. dapat berjalan sampai setelah operasi itu selesai.Biaya
GC.KeepAlive()
danGC.SuppressFinalize(this)
pada dasarnya sama di setiap kelas yang tidak memiliki finalizer, dan kelas yang memiliki finalizer umumnya harus memanggilGC.SuppressFinalize(this)
, jadi menggunakan fungsi yang terakhir sebagai langkah terakhirDispose()
mungkin tidak selalu diperlukan, tetapi tidak akan diperlukan. salahsumber