簡體   English   中英

CLR什么時候說對象有終結器?

[英]When does CLR say that an object has a finalizer?

我知道在C#中,如果你編寫~MyClass() ,這基本上轉換為override System.Object.Finalize() 因此,無論您是否編寫析構函數 ,CLR中的每個類型都將包含一個Finalize()方法(至少是System.Object )。

1]那么,這是否意味着,默認情況下,每個對象都有一個終結器?

2] CLR決定一個對象應該通過終結隊列的基礎是什么?

我問這個,因為,我有一個類,說ManagedResourceHolder實現了IDisposable ,但沒有在其IDisposable.Dispose()方法中調用GC.SuppressFinalize(this) 該類沒有任何非托管資源,並且不需要~ManagedResourceHolder()方法,這反過來意味着不需要GC.SuppressFinalize(this)調用,因為沒有終結器

3]在上述場景的上下文中,在實現IDisposable時是否總是需要提供終結器? (即使在沒有非托管資源的類上)

該FxCop的規則CA1816是給我一個違反了這一點,我得到的回應在這里 ,當我問在MSDN上的CA論壇搞糊塗了。

謝謝。

問題1和2 :CLR基本上檢查終結器是否被覆蓋。 如果不是,它會將其視為沒有終結器。

在System.Object中使用終結器的好處是編譯器知道他們總是可以調用base.Finalize() 。這可以避免版本控制問題。 考慮一個沒有System.Object.Finalize()的世界:

  • System.Object(沒有Finalize)
  • Acme.BaseClass(沒有Finalize)
  • MyCompany.DerivedClass(Finalize)

如果沒有對象中的Finalize方法,MyCompany.DerivedClass中的終結器不能調用任何東西。 當Acme.BaseClass的第2版帶有終結器時會導致問題。 除非您重新編譯MyCompany.DerivedClass,否則DerivedClass的實例將在不調用BaseClass.Finalize的情況下完成,這顯然是一件壞事。

現在考慮 System.Object.Finalize相同的情況 - 編譯器在DerivedClass.Finalize中自動插入對base.Finalize的調用,在版本1中只調用System.Object中的no-op實現。 當Acme.BaseClass的第2版出來時,對base.Finalize的調用將(無需重新編譯DerivedClass)調用BaseClass.Finalize。

問題3 :不,您不需要因為實現IDisposable而擁有終結器。 終結器應僅用於非托管資源, 其他任何東西都不會被清理 - 即您可以直接引用的資源。 例如,假設您有一個具有FileStream成員變量的類。 您希望實現IDisposable以便您可以盡快關閉流,如果調用者記得 - 但如果他們記得調用Dispose() ,則該流將有資格與您的對象同時進行垃圾回收。 相信FileStream有一個合適的終結器(或者使用終結器等對其他東西的引用),而不是試圖在你自己的終結器中清理它。

從.NET 2.0開始,使用SafeHandle類,您需要自己的終結器應該是非常罕見的。

1:它只是被重寫(在有用的意義上)

2:由1定義,並且沒有調用GC.SuppressFinalize(加上重新注冊等)

3:當然不是; 實際上,除非您直接處理非托管資源,否則您應該使用終結器。 你不應該僅因為它是IDisposable而添加終結器 - 但是具有終結器的東西通常也應該是IDisposable。

  1. 不,這並不意味着。 只有被覆蓋的Finalize()才會被CLR計算。
  2. 通過具有如上定義的終結器。
  3. 不,這並不總是必要的。 這只是一個很好的模式。 我的意思是,沒有人強迫你這樣做。 但是,如果你有非托管資源,這是一件好事,因為如果有人忘記處理它,非托管資源將在某個時候被釋放。 FxCop不強制執行嚴格的規則。 如果您不照顧,它會強制執行可能導致將來失敗的良好模式。

更新:每個班級都負責管理自己的資源。 由於面向對象范例的抽象和封裝特性,類的消費者不應該間接關注它擁有的資源。 因此,您應該手動釋放您擁有的資源(您擁有的是您在將其他東西視為黑盒時 直接擁有的資源)或將其留給GC以釋放它們。 對於非托管資源,您無法將其保留到GC,因此必須手動釋放它。 從這個意義上講,Jon提到的SafeHandle是非托管資源托管抽象 ,因此它應被視為有價值的托管資源(這是一個黑盒子,用於管理非托管資源本身的最終化)。

1)是(憑借繼承)

2)沒有任何東西持有對類實例的引用(這將使其有資格完成)

3)是(為什么一個人應該實現IDisposable,除非它要求用戶明確地調用dispose?.net中的連接類使用一個非管理資源並且如果你不調用dispose,它將依賴它。由於GC時間未知,連接將保持打開,直到那個時間)

這是我的理解。

我錯了。 在這種情況下,專家會為我糾正問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM