C#.NET对象处理

Nic*_*ick 8 .net c# garbage-collection dispose object

应该是一个简单的.假设我有以下代码:

void Method()
{
   AnotherMethod(new MyClass());
}

void AnotherMethod(MyClass obj)
{
   Console.WriteLine(obj.ToString());
}
Run Code Online (Sandbox Code Playgroud)

如果我调用"Method()",那么在该过程中创建的MyClass对象会发生什么?它是否仍然存在于调用后的堆栈中,即使没有使用它?还是会立即删除?

我是否必须将其设置为null才能让GC更快地注意到它?

Jar*_*Par 13

在对Method完成调用之后,您的MyClass对象仍处于活动状态,但是没有从root值引用它.因此它将一直存在,直到下一次GC运行,它将被收集并回收内存.

除了强制GC之外,您无法做任何事情来加速此过程.然而,这可能是一个坏主意.GC旨在清理此类对象,并且您为使其更快而进行的任何尝试都可能导致整体速度变慢.您还会发现GC在正确清理托管对象的同时,实际上可能不会减少系统中的内存.这是因为GC保留它以备将来使用.这是一个非常复杂的系统,通常最好留给它自己的设备.


Eri*_*ert 7

如果我调用"Method()",那么在该过程中创建的MyClass对象会发生什么?

它在GC堆上创建.然后,在堆中放置对其在堆中的位置的引用.然后调用AnotherMethod.然后调用对象的ToString方法并打印出结果.然后AnotherMethod返回.

它是否仍然存在于调用后的堆栈中,即使没有使用它?

你的问题很模糊."通话"是指对Method或AnotherMethod的调用?它有所不同,因为此时,堆内存是否是垃圾收集的候选者取决于您是否通过打开或关闭优化进行编译.我将略微改变你的程序来说明差异.假设你有:

void Method() 
{ 
   AnotherMethod(new MyClass()); 
   Console.WriteLine("Hello world");
} 
Run Code Online (Sandbox Code Playgroud)

关闭优化后,我们有时会生成如下代码:

void Method() 
{ 
   var temp = new MyClass();
   AnotherMethod(temp); 
   Console.WriteLine("Hello world");
} 
Run Code Online (Sandbox Code Playgroud)

在未优化的版本中,运行时实际上会选择将对象视为不可收集,直到在WriteLine之后返回Method.在优化版本中,运行时可以选择在AnotherMethod返回之前,在WriteLine之前将对象视为可收集的.

产生差异的原因是因为在调试会话期间使对象生命周期更容易预测通常可以帮助人们理解他们的程序.

还是会立即删除?

没有立即收集; 当垃圾收集器感觉它应该运行时运行.如果您需要在完成后立即清理某些资源(如文件句柄),请使用"使用"块.如果没有,那么让垃圾收集器决定何时收集内存.

我是否必须将其设置为null才能让GC更快地注意到它?

你必须设置什么为null?你有什么变量?

无论如何,你不要做任何事情,使垃圾收集工作.它独立运行,没有你的提示.

我认为你是在思考这个问题.让垃圾收集器做它的事情,不要强调它.如果你的内存没有得到及时收集的真实问题,请向我们展示一些说明问题的代码; 否则,只需放松并学会爱自动存储回收.

  • 我认为你的假设不太可能真正解释序列化问题.是否有对象的*field*包含对不可序列化对象的引用? (2认同)