带有对象引用的C#垃圾回收
本文关键字:对象引用 | 更新日期: 2023-09-27 18:01:07
在C#中,当我有两个对象obj1、obj2由一个List<string>
组成时,我将这两个对象都分配给同一个List<string>
对象。
如果我对obj1的引用超出了范围,但对obj2的引用没有超出范围,那么obj1是否仍然有资格进行垃圾收集,或者是否因为仍然有对List<string>
对象的引用而存在一些依赖性问题?
obj1就应该有资格进行垃圾收集。
如果我对obj1的引用超出范围,但我对obj2的引用确实不是,obj1仍然有资格吗垃圾收集,或者有一些依赖性问题,因为仍然是对列表的引用对象
如果我理解正确,您的意思是obj1
和obj2
都属于List<string>
类型,并且都指向相同的List<string>
实例。
当obj1
超出范围时,仍然会有obj2
作为对List<string>
实例的活动引用,因此不能对列表进行垃圾收集。
如果obj1是堆上引用类型(即其属性之一(的一部分,则它所占用的内存空间可能会作为外部对象的一部分进行垃圾收集。如果它只是堆栈上的引用,则不会涉及GC,因为当obj1超出范围时,堆栈将在方法调用结束时展开。
请记住,obj1只是对堆上某个对象的引用(在某种程度上是一个指针(——只有当不再有引用指向该对象时,该对象才可能被垃圾收集。
在您的情况下,obj1
必须有资格进行垃圾收集。
您需要在此处查看Jon Skeet's
answer
。它清楚地解释了垃圾回收是如何在对象引用上工作的。
一个很好的Object's Lifetime in C#
教程。
这个问题中定义了内存的三种用途:
- 对被称为CCD_ 16的单个CCD_
- 对被称为CCD_ 18的单个CCD_
List<string>
如果obj1
超出范围,但obj2
没有超出范围,则垃圾回收后只剩下以下内容:
- 对被称为CCD_ 23的CCD_
List<string>
重要的是要记住,C#在大多数情况下都抽象掉了引用的概念,这样你就可以放心地将obj1
和obj2
视为List<string>
,而不是引用,而是引用它们。
obj1
引用可能在本地调用堆栈中,而实例本身可能在堆中。因此,obj1
(引用(仅在调用堆栈展开时才被清理。
如果obj1
是List的成员,则在父List被垃圾收集之前,它不可用于垃圾收集。
因此:
List<string> l = new List<string>();
string a = "one";
l.Add(a);
{
string b = "two";
l.Add(b);
}
在该列表的末尾,a
在作用域内,b
在作用域外,但两者在列表l
中仍有引用,因此两者都不符合垃圾收集的条件。