[c#] 在.NET中使用後將對象設置為Null / Nothing



Answers

避免將對象設置為null的另一個原因是,它可以使對象保持更長時間的活動狀態。

例如

void foo()
{
    var someType = new SomeType();
    someType.DoSomething();
    // someType is now eligible for garbage collection         

    // ... rest of method not using 'someType' ...
}

將允許在調用“DoSomething”之後將someType引用的對象進行GC'd處理,但是

void foo()
{
    var someType = new SomeType();
    someType.DoSomething();
    // someType is NOT eligible for garbage collection yet
    // because that variable is used at the end of the method         

    // ... rest of method not using 'someType' ...
    someType = null;
}

有時可能會使對象保持活動直到方法結束。 JIT通常會將賦值優化為空 ,因此這兩個代碼最終都是相同的。

Question

一旦你完成了它們,你應該把所有的對像都設置為null (VB.NET中Nothing )?

我明白,在.NET中,處理實現IDisposable接口的對象的任何實例都是必要的,以釋放一些資源,儘管該對像在處置後仍然是某些東西(因此表單中的isDisposed屬性),所以我認為它可以仍然駐留在記憶中或至少部分?

我也知道,當一個對象超出範圍時,它會被標記為垃圾收集器的下一個傳遞的收集(儘管這可能需要時間)。

因此,考慮到這一點,將它設置為null加快系統釋放內存的速度,因為它不必解決它不在範圍內,並且它們有任何不良副作用?

MSDN文章從來沒有在例子中做到這一點,目前我這樣做,因為我不能看到傷害。 不過,我遇到了各種意見,所以任何意見都是有用的。




如果您覺得需要null變量,那麼您的代碼結構可能不夠緊密。

有很多方法可以限制變量的範圍:

正如史蒂夫Tranby所述

using(SomeObject object = new SomeObject()) 
{
  // do stuff with the object
}
// the object will be disposed of

同樣,你可以簡單地使用大括號:

{
    // Declare the variable and use it
    SomeObject object = new SomeObject()
}
// The variable is no longer available

我發現使用沒有任何“標題”的大括號來真正清理代碼並且使其更容易理解。




我相信通過設計GC實現器,您無法加速 GC與廢除。 我相信他們更喜歡你不用擔心GC的運行方式/時間 - 像這種無處不在的一樣保護和監視你的行為......(低頭向下,向天空揮拳).. 。

就我個人而言,當我將它們作為自我文檔的一種形式完成時,我經常明確地將變量設置為null。 我沒有聲明,使用,然後設置為null - 在不再需要它們之後立即將其設為null。 我明確地說,“我已經與你正式完成......離開......”

在GC'd語言中是否需要廢止? 不是。它對GC有幫助嗎? 也許是的,也許不是,一定不知道,在設計上我真的無法控制它,不管今天的答案是這個版本還是那個,未來的GC實現可能會改變超出我的控制範圍的答案。 此外,如果/當nulling被優化出來,如果你願意,它不過是一個奇特的評論

我想,如果這讓我更加清楚下一個跟隨我腳步的可憐的傻瓜,並且如果它“有可能”有時可能幫助GC,那麼這對我來說是值得的。 大多數情況下,這讓我感覺整潔清晰,蒙戈喜歡整潔清晰。 :)

我看起來就像這樣:編程語言的存在是為了讓別人給他們一個意圖的概念,一個編譯器提供一個工作請求 - 編譯器將這個請求轉換成一個不同的語言(有時候是幾個CPU) CPU可以提供你使用的語言,你的標籤設置,註釋,風格重點,變量名等等.CPU的所有關於比特流的信息都會告訴它哪些寄存器,操作碼和內存位置是否可以旋轉。 用代碼編寫的許多東西不會按照我們指定的順序轉換成CPU所消耗的東西。 我們的C,C ++,C#,Lisp,Babel,彙編程序或任何其他理論而不是現實,都是作為工作陳述寫成的。 你看到的不是你得到的,是的,即使是彙編語言。

我確實理解“不必要的東西”(如空白行)的思維方式“只是噪音和雜亂的代碼。” 那是我職業生涯的早些時候; 我完全明白這一點。 在這個時候,我傾向於使代碼更清晰。 這不像我在我的程序中添加50行“噪音” - 這里或那裡只有幾行。

任何規則都有例外。 在具有易失性存儲器,靜態存儲器,競態條件,單例,使用“陳舊”數據以及所有類型的腐敗的情況下,這是不同的:你需要管理自己的內存,鎖定和取消為apropos,因為內存不是GC'd宇宙 - 希望每個人都明白這一點。 其餘時間使用GC語言,這是一個風格問題,而不是必要的問題,或者保證性能提升。

在一天結束時,確保你了解什麼是符合GC的條件,哪些不符合; 鎖定,處置和適當的廢除; 打蠟,打蠟; 呼吸,呼吸; 對於我說的所有其他事情:如果感覺很好,那就去做吧。 你的里程可能會有所不同......因為它應該......




只有當變量沒有超出範圍並且不再需要與其關聯的數據時,您才應該將變量設置為null。 否則就沒有必要。




在某些情況下,空引用是有意義的。 例如,當你寫一個集合 - 比如一個優先級隊列 - 和你的合約時,你不應該在客戶端將它們從隊列中刪除之後讓這些對象保持活動狀態。

但這種事情只對長壽的收藏品很重要。 如果隊列在其創建的函數結束時不能存活,那麼它的重要性就會降低很多。

總的來說,你真的不應該打擾。 讓編譯器和GC做他們的工作,這樣你就可以做你的工作。




一般來說,使用後不需要清空對象,但在某些情況下,我認為這是一個好習慣。

如果一個對象實現了IDisposable並存儲在一個字段中,我認為它很好,以避免使用處置對象。 下面的錯誤可能是痛苦的:

this.myField.Dispose();
// ... at some later time
this.myField.DoSomething();

在處理它之後清空這個字段是很好的,並且在再次使用這個字段的那一行得到一個NullPtrEx。 否則,你可能會遇到一些神秘的bug(具體取決於DoSomething的作用)。






Related