2013-11-21 67 views
2

我有以下代碼:編譯器是否將處置的對象設置爲null?

public class Program 
{ 
private static Task task; 
private static int counter = 0; 

private static void Main(string[] args) 
{ 
    for (int i = 0; i < 10; i++) 
    { 
    if (task == null) 
    { 
     Console.WriteLine(++counter); 
    } 

    using (task = new Task(Method)) 
    { 
     task.Start(); 
     task.Wait(); 
    } 

    // task = null; 

    GC.Collect(); 
    GC.WaitForPendingFinalizers(); 
    } 

    Console.ReadKey(); 
} 

public static void Method() { } 
} 

我的除外輸出:1 2 3 4 5 6 ...但這種方法的實際輸出爲1!

如果我從代碼行Task = null;刪除評論,那麼我將成爲預期的結果。

爲什麼處置的任務不是空的!?我想,如果物品被丟棄,那麼它們可以被設置爲GC(我已經強制GC收集),換句話說,GC會收集已處置(孤立)的物體並將它們置於空?!

+0

我發現了一個非常有用的問題鏈接:http://stackoverflow.com/questions/2926869/do-you-need-to-dispose-of-objects-and-set-them-to-null –

回答

6

爲什麼你會期望它被設置爲nullusing/Dispose()從來沒有說它會這樣做。它承諾配置它。這裏最好的做法是使用一個單獨的變量在using聲明,以避免混淆:

using(var t = new Task(Method)) 
{ 
    t.Start(); 
    t.Wait(); 
} 

但是如果你想將其設置爲空; 它設置爲null

task = null; 

至於你的其他觀點:

換句話說,GC將收集的配置(孤兒)對象,並把他們的空?

GC從未設置任何內容到null;它收集的東西是無法訪問的:那全是

+0

非常感謝,這正是我需要知道的! –

2

我不確定你的意思是編譯器。如果你的意思是「c#編譯器」,那麼代碼執行時就沒有業務了。它只是編寫了IL的c#代碼。就是這樣,休息一切都由CLR和JIT照顧。

對於您的問題:不,沒有人在處置時設置對null的引用。這是你的責任,當你不需要它的時候設置爲null。

GC將只收集無法訪問的對象。換句話說,當你沒有對你的實例的託管引用時,它有資格進行垃圾回收。

2

所有靜態字段,例如您的task字段,都是GC根。從GC根目錄可訪問的對象將不會被收集。

GC也不會將null引用清空,也不需要,因爲不可達對象在任何線程的作用域中都不會有任何活動引用。

+0

感謝您提供此信息並獲得正確答案。這只是我剛剛描述問題的一個原型。我已經標記了Marc的答案,因爲答案對我來說很清楚。 –

相關問題