是否可以编写C#以便在对象超出范围时对其进行垃圾回收?

时间:2010-01-27 21:00:09

标签: c# garbage-collection

例如,在下面的代码中,将创建一个'image'对象,然后在未来某个未知点收集垃圾

void MyFunction() {

    Bitmap image = RetrieveImage();
    DoSomething(image);
}

怎么样?
void MyFunction() {

    DoSomething(RetrieveImage());

}

在这种情况下,一旦它移出范围,即在MyFunction结束后收集的对象垃圾。如果没有,有什么地方可以强制执行吗?

4 个答案:

答案 0 :(得分:19)

没有。事实上,你并不真的希望它被垃圾收集 - 频繁地提示垃圾收集器会降低性能。

要做的想要的是及时处理非托管资源 - 这就是IDisposable所带来的地方,以及using声明:

void MyFunction()
{
    using (Bitmap image = RetrieveImage())
    {
        DoSomething(image);
    }
}

image.Dispose()语句离开using语句时,无论DoSomething是否引发异常,都会调用DoSomething

你必须使用额外的变量 - 除非你改为Func<Bitmap>取代void DoSomething(Bitmap image) { // Code here } ... DoSomething(RetrieveImage()); ,所以代替:

void DoSomething(Func<Bitmap> imageProvider)
{
    using (Bitmap image = imageProvider())
    {
        // Code here
    }
}
...
DoSomething(() => RetrieveImage());
你有:

RetrieveImage

请注意,这并没有机会传递位图而没有它被处理 - 如果你想稍后再使用它可能会有问题。不过,至少知道它是一种很好的技术。

编辑:正如mbeckish在他的评论中指出的那样,仅仅在public void ApplyToEachLineInFile(string file, Action<string> action) { using (TextReader reader = File.OpenText(file)) { string line; while ((line = reader.ReadLine()) != null) { action(line); } } } 内处理位图并没有太大的好处。以下是该模式的变体:

{{1}}

这里封装了“获取和处理”逻辑,而不会让调用者担心 - 但调用者在传递的逻辑复杂性方面仍然可以非常灵活。

答案 1 :(得分:4)

当对象超出范围时,不会发生垃圾收集。相反,它是框架中的自动内存管理功能。

http://msdn.microsoft.com/en-us/magazine/bb985010.aspx

你可以强迫.Net收集垃圾,但除非你遇到严重的内存问题,否则我不建议你走这条路。

答案 2 :(得分:3)

注意:您不想这样做。 .NET垃圾收集器比你(或我,或Jon Skeet或其他任何人)“更聪明”。

try
{
    Bitmap image = RetrieveImage();
    DoSomething(image);
}
finally
{
    GC.Collect();
}

(假设没有任何超出范围的对象实现IDisposable)

答案 3 :(得分:0)

您可以使用以下命令强制执行垃圾收集:

System.GC.Collect()

正确处理后(请参阅Jons答案for using(){} - 语法)。

&LT;编辑&gt;

不要忘记(就像我刚才那样)

System.GC.WaitForPendingFinalizers();

之后。

&LT; /编辑&gt;

虽然不建议 - 正如乔恩所说。