Pembaruan (1 Desember 2009):
Saya ingin mengubah jawaban ini dan mengakui bahwa jawaban yang asli salah.
Analisis asli memang berlaku untuk objek yang membutuhkan finalisasi - dan titik bahwa praktik tidak boleh diterima di permukaan tanpa pemahaman yang akurat dan mendalam masih berlaku.
Namun, ternyata DataSets, DataViews, DataTables menekan finalisasi dalam konstruktor mereka - inilah mengapa memanggil Buang () pada mereka secara eksplisit tidak melakukan apa-apa.
Agaknya, ini terjadi karena mereka tidak memiliki sumber daya yang tidak dikelola; jadi terlepas dari kenyataan bahwa MarshalByValueComponent membuat penyisihan untuk sumber daya yang tidak dikelola, implementasi khusus ini tidak memiliki kebutuhan dan karenanya dapat melupakan finalisasi.
(Bahwa. NET penulis akan berhati-hati untuk menekan finalisasi pada tipe yang biasanya menempati sebagian besar memori berbicara tentang pentingnya praktik ini secara umum untuk tipe yang dapat diselesaikan.)
Sekalipun demikian, detail-detail ini masih kurang didokumentasikan sejak dimulainya .NET Framework (hampir 8 tahun yang lalu) cukup mengejutkan (bahwa Anda pada dasarnya dibiarkan menggunakan perangkat Anda sendiri untuk menyaring material yang bertentangan namun ambigu untuk menyatukan potongan-potongan tersebut. kadang membuat frustasi tetapi memberikan pemahaman yang lebih lengkap tentang kerangka kerja yang kita andalkan sehari-hari).
Setelah banyak membaca, inilah pemahaman saya:
Jika suatu objek membutuhkan finalisasi, ia dapat menempati memori lebih lama dari yang seharusnya - inilah alasannya: a) Setiap jenis yang mendefinisikan destruktor (atau mewarisi dari tipe yang mendefinisikan destruktor) dianggap dapat diselesaikan; b) Pada alokasi (sebelum konstruktor berjalan), sebuah pointer ditempatkan pada antrian Finalisasi; c) Objek yang dapat diselesaikan biasanya membutuhkan 2 koleksi untuk direklamasi (bukan standar 1); d) Menekan finalisasi tidak menghapus objek dari antrian finalisasi (seperti yang dilaporkan oleh! FinalizeQueue di SOS) Perintah ini menyesatkan; Mengetahui objek apa yang ada pada antrian finalisasi (dengan sendirinya) tidak membantu; Mengetahui objek apa yang ada pada antrian finalisasi dan masih membutuhkan finalisasi akan sangat membantu (apakah ada perintah untuk ini?)
Menekan finalisasi sedikit mematikan di header objek yang mengindikasikan ke runtime bahwa ia tidak perlu meminta Finalizer-nya dipanggil (tidak perlu memindahkan antrian FReachable); Masih dalam antrian Finalisasi (dan terus dilaporkan oleh! FinalizeQueue di SOS)
Kelas DataTable, DataSet, DataView semuanya di-root di MarshalByValueComponent, objek yang dapat diselesaikan yang dapat (berpotensi) menangani sumber daya yang tidak dikelola
- Karena DataTable, DataSet, DataView tidak memperkenalkan sumber daya yang tidak dikelola, mereka menekan finalisasi dalam konstruktor mereka
- Meskipun ini adalah pola yang tidak biasa, itu membebaskan penelepon dari harus khawatir tentang panggilan Buang setelah digunakan
- Ini, dan fakta bahwa DataTable berpotensi dibagikan di berbagai DataSets, kemungkinan mengapa DataSets tidak peduli untuk membuang DataTables anak
- Ini juga berarti bahwa objek-objek ini akan muncul di bawah! FinalizeQueue di SOS
- Namun, objek-objek ini harus tetap dapat direklamasi setelah satu koleksi, seperti rekanannya yang tidak dapat diselesaikan
4 (referensi baru):
Jawaban asli:
Ada banyak jawaban yang menyesatkan dan umumnya sangat buruk tentang ini - siapa pun yang mendarat di sini harus mengabaikan kebisingan dan membaca referensi di bawah ini dengan cermat.
Tanpa ragu, Buang harus dipanggil pada objek yang dapat diselesaikan .
DataTables yang Finalizable.
Memanggil Buang secara signifikan mempercepat pengambilan kembali memori.
Panggilan MarshalByValueComponent GC.SuppressFinalize (this) dalam Buangnya ( ) - melewatkan ini berarti harus menunggu puluhan jika tidak ratusan koleksi Gen0 sebelum memori direklamasi:
Dengan pemahaman dasar finalisasi ini, kita dapat menyimpulkan beberapa hal yang sangat penting:
Pertama, objek yang membutuhkan finalisasi hidup lebih lama dari objek yang tidak. Bahkan, mereka bisa hidup lebih lama. Sebagai contoh, misalkan objek yang ada dalam gen2 perlu diselesaikan. Finalisasi akan dijadwalkan tetapi objek masih dalam gen2, sehingga tidak akan dikumpulkan kembali sampai pengumpulan gen2 berikutnya terjadi. Itu bisa menjadi waktu yang sangat lama, dan, pada kenyataannya, jika semuanya berjalan baik itu akan menjadi waktu yang lama, karena koleksi gen2 mahal dan dengan demikian kami ingin itu terjadi sangat jarang. Objek yang lebih tua yang membutuhkan finalisasi mungkin harus menunggu puluhan jika tidak ratusan koleksi gen0 sebelum ruang mereka direklamasi.
Kedua, objek yang membutuhkan finalisasi menyebabkan kerusakan jaminan. Karena pointer objek internal harus tetap valid, tidak hanya objek yang secara langsung membutuhkan finalisasi berlama-lama di memori, tetapi segala sesuatu yang dirujuk oleh objek, secara langsung dan tidak langsung, juga akan tetap ada dalam memori. Jika pohon besar benda berlabuh oleh satu objek yang membutuhkan finalisasi, maka seluruh pohon akan berlama-lama, berpotensi untuk waktu yang lama seperti yang baru saja kita bahas. Oleh karena itu penting untuk menggunakan finalizer dengan hemat dan menempatkannya pada objek yang memiliki pointer objek internal sesedikit mungkin. Dalam contoh pohon yang baru saja saya berikan, Anda dapat dengan mudah menghindari masalah dengan memindahkan sumber daya yang membutuhkan penyelesaian ke objek yang terpisah dan menyimpan referensi ke objek tersebut di akar pohon.
Akhirnya, objek yang membutuhkan finalisasi membuat pekerjaan untuk thread finalizer. Jika proses finalisasi Anda adalah proses yang kompleks, utas satu-satunya dan finalizer akan menghabiskan banyak waktu melakukan langkah-langkah tersebut, yang dapat menyebabkan tumpukan pekerjaan dan karena itu menyebabkan lebih banyak objek berlama-lama menunggu untuk finalisasi. Karena itu, sangat penting bagi para finalis untuk melakukan sesedikit mungkin pekerjaan. Ingat juga bahwa meskipun semua pointer objek tetap valid selama finalisasi, mungkin saja pointer tersebut mengarah ke objek yang telah diselesaikan dan karenanya mungkin kurang bermanfaat. Biasanya paling aman untuk menghindari mengikuti pointer objek dalam kode finalisasi meskipun pointer valid. Jalur kode finalisasi yang aman dan singkat adalah yang terbaik.
Ambillah dari seseorang yang melihat 100 MB dari DataTables yang tidak direferensikan di Gen2: ini sangat penting dan benar-benar terlewatkan oleh jawaban di utas ini.
Referensi:
1 -
http://msdn.microsoft.com/en-us/library/ms973837.aspx
2 -
http://vineetgupta.spaces.live.com/blog/cns!8DE4BDC896BEE1AD!1104.entry
http://www.dotnetfunda.com/articles/article524-net-best-practice-no-2-improve-garbage -collector-performance-using-finalizedispose-pattern.aspx
3 -
http://codeidol.com/csharp/net-framework/Inside-the-CLR/Automatic-Memory-Management/