创建IEnumerable<T>类型对象是否会生成需垃圾回收的堆对象?
关于IEnumerable对象与堆内存及垃圾回收的说明
是的,当你通过带yield return的方法创建IEnumerable<T>类型对象时,确实会在堆上生成最终需要垃圾回收的对象。
具体原因
C#编译器会自动将包含yield return的迭代器方法,转换为一个实现了IEnumerable<T>和IEnumerator<T>接口的状态机类。当你调用这类方法(比如示例中的GetOneTwoThree())时,实际上是实例化了这个状态机类的对象——而这个状态机对象属于引用类型,必然在堆上分配内存。当该对象不再被任何引用指向时,就会被垃圾回收器标记为待回收对象。
结合示例说明
看你给出的代码示例:
IEnumerable<int> GetOneTwoThree() { yield return 1; yield return 2; yield return 3; }
当执行var numbers = GetOneTwoThree();时,numbers变量指向的就是编译器生成的状态机实例。后续的foreach循环会驱动这个状态机逐步执行yield return的逻辑,输出1、2、3。遍历完成后,如果没有其他代码再引用numbers,这个状态机对象就会成为垃圾回收的目标。
另外要注意:哪怕是直接返回一个集合(比如return new List<int> {1,2,3};)来得到IEnumerable<T>对象,集合本身也是堆上的引用类型对象,同样会被垃圾回收——区别只是用yield时,堆上的对象是编译器自动生成的状态机,而非你手动创建的集合实例。
内容的提问来源于stack exchange,提问作者Amos Egel
相关产品推荐
相关产品推荐

