2013-11-21 28 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的答案,因为答案对我来说很清楚。 –

相关问题