2013-04-18 70 views
1

我們有構造函數,我們可以將它們視爲對象實例化的合同。爲什麼沒有處理合同?

沒有其他的方法來創建一個實例,但沒有爲構造函數提供一組精確的參數。

但是,我們如何(我們應該打擾)執行一些驗前活動? 我們已經有終結器,但不推薦用於通用終結。 我們也有IDisposable來執行。但是,如果我們使用不帶using的一次性物品,我們無法保證Dispose永遠不會被調用。

爲什麼現在有辦法強制對象的某些狀態,然後纔會放開?

因爲不能保證對象圖是完整的,並且死亡對象的引用對象還沒有被GC取消,所以在終結器中進行添加是不可能的。

當然,客戶端代碼不會調用實例對象的SaveState()會給它帶來一些麻煩,而不是我的對象。

儘管如此,要求在構造函數中注入所有需要的依賴項(如果沒有默認值可用)被認爲是一種好的做法。沒人願意說:「如果對象處於無效狀態,則保留默認構造函數,創建屬性並拋出異常。」

更新:

由於有關閉我想說的是一些設計模式,這也可能是一個答案的問題很多選票。

無論您是否使用DI,您都可以計算請求/創建對象的次數。但是,如果沒有明確的釋放調用,則不知道應該調用處置的時刻。

我根本不明白如何在正確的時間實施處置。

+1

這樣的合同是不可能執行的。 – SLaks

+3

這聽起來更像是一個咆哮,而不是一個問題。 –

+3

做一個完整的一次性模式(與終結者作爲備份)是最接近你可以得到:http://www.codeproject.com/Articles/15360/Implementing-IDisposable-and-the-Dispose-Pattern-P – Thorarin

回答

12

爲什麼沒有辦法強制一些對象的狀態,然後纔會放開?

由於垃圾收集的全部要點是simulate a machine that has an infinite amount of memory。如果記憶是無限的,那麼你永遠不需要清理它。

你混爲一談程序的語義要求 - 一個特定的副作用發生在一個特定的時間 - 與模擬無限存儲的機制。在理想的世界裏,這兩件事不應該有任何關係。不幸的是,我們生活在一個理想的世界裏,終結者的存在就是這方面的證據。

如果有您想要達到在某一特定時間的影響,然後那些影響你的程序的一部分,你應該說達到他們寫代碼。如果它們很重要,那麼它們應該在代碼中可見,以便閱讀代碼的人可以看到並理解它們。

+0

事實上,一個對象可能需要請求其他實體代表其他實體 - 這對其他實體不利 - 直到它知道它不再被要求做任何事情,這幾乎不是一個意想不到的實現細節。其他實體是誰以及他們要求的是實施細節,但事實上,一個對象可能要求其他實體代表它行事,在很多情況下應該是*預期*。這樣的語義是經常需要的,應該與垃圾收集無關。唉,很少有語言似乎認真對待這個問題。 – supercat

2

不幸的是,在設計Java期間,預計垃圾收集器應該能夠滿足所有的清理要求。這似乎也是.NET早期設計階段的一個信念。

因此,不區分兩種情況:

  • 一個object reference它封裝其目標的獨佔所有權;

  • a reference to an object其中不是封裝所有權(其目標由其他人擁有);

  • 一個reference whose owner知道它要麼封裝獨家擁有封裝無,並且知道這種情況下,適用於手頭的實例;

  • object reference它封裝共享所有權。

如果語言和框架,圍繞這樣的差別進行了適當設計的,它很少會需要編寫代碼,其中適當的清理不能靜態地驗證(在前兩種情況下,這可能適用的90%的時間+ ,即使使用.NET框架也可以輕鬆進行靜態驗證)。

不幸的是,由於在非常有限的語句範圍之外不存在這樣的區別,因此編譯器或驗證程序無法知道,某段代碼何時放棄引用,是否有其他任何事情正在期望清理該對象由此提及。

因此,沒有辦法一般瞭解對象是否應該處置,後無來者發牢騷如果應該的話,但不是一般的,有意義的方式。

相關問題