Unm*_*kar 9 .net garbage-collection
在他的博客中,什么时候对象可用于垃圾收集?,Reymond Chen写道
在该对象上执行方法期间,对象可以符合收集条件.
此外,Curt Nichols通过这个例子展示了同样的观点
public class Program
{
static void Main(string[] args)
{
new TestClass().InstanceMethod();
Console.WriteLine("End program.");
Console.ReadLine();
}
}
public sealed class TestClass
{
private FileStream stream;
public TestClass()
{
Console.WriteLine("Ctor");
stream = new FileStream(Path.GetTempFileName(), FileMode.Open);
}
~TestClass()
{
Console.WriteLine("Finializer");
stream.Dispose();
}
public void InstanceMethod()
{
Console.WriteLine("InstanceMethod");
StaticMethod(stream);
}
private static void StaticMethod(FileStream fs)
{
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine("StaticMethod");
var len = fs.Length;
}
}
Run Code Online (Sandbox Code Playgroud)
输出如预期 -
Ctor
InstanceMethod
Finalizer
StaticMethod
ObjectDisposedException is thrown
Run Code Online (Sandbox Code Playgroud)
在这个例子中,我无法理解GC如何收集临时TestClass对象,因为它的成员stream被引用StaticMethod.
是的,雷蒙德说
GC不是追踪根,而是关于删除不再使用的对象
但是,在这个例子中TestClass对象仍在使用,不是吗?
请解释一下GC TestClass在这种情况下收集对象的权利如何?此外,更重要的是,开发人员应如何防范这些情况?
我无法理解GC是如何收集临时TestClass对象的,因为StaticMethod引用了它的成员流.
StaticMethod实际上并没有持有TestClass实例的stream成员的引用 - 它持有对引用(就GC而言)堆上的一些 FileStream对象.
请注意C#的默认传值语义.在这个声明中:
StaticMethod(stream);
Run Code Online (Sandbox Code Playgroud)
甲复制的值的stream字段被作为参数传递给静态方法通过.FileStream是引用类型,引用类型表达式的值是引用.因此,FileStream对堆上对象的引用将传递给方法,而不是(如您所想的那样)对TestClass对象的引用/内部引用
调用此FileStream对象时仍可访问的事实不会导致使对象(创建它并通过字段引用它)也可以访问."实时"对象通过引用它们使其他对象生动,而不是通过它们引用它们.GC.CollectTestClass
假设优化导致不需要的引用被"弹出",让我们看一下创建TestClass对象的可达性.
Main 调用后不需要引用它:InstanceMethod,在this取消引用它以读取stream字段后,又不需要隐式传递的引用.此对象有资格进行收集.然后它调用:StaticMethod反过来(如前所述)根本没有持有对象的引用.因此,在读取TestClass其stream字段之后不需要该对象,并且在 StaticMethod执行时肯定有资格进行收集.
| 归档时间: |
|
| 查看次数: |
303 次 |
| 最近记录: |