【发布时间】:2010-10-08 03:37:44
【问题描述】:
我的一位同事声称,在 C# 中,在非静态类中包含静态成员可以防止这些类的实例被垃圾收集,这是 C# 内存泄漏的常见来源。因此,他总是将静态成员包装在静态类中,并通过该静态类上的静态属性或方法从那里获得对它们的访问。我一直认为静态是在堆栈上,而不是在堆上,因此与垃圾收集没有任何关系。这对我来说似乎不对。
这件事的真相是什么?
【问题讨论】:
标签: c# static garbage-collection
我的一位同事声称,在 C# 中,在非静态类中包含静态成员可以防止这些类的实例被垃圾收集,这是 C# 内存泄漏的常见来源。因此,他总是将静态成员包装在静态类中,并通过该静态类上的静态属性或方法从那里获得对它们的访问。我一直认为静态是在堆栈上,而不是在堆上,因此与垃圾收集没有任何关系。这对我来说似乎不对。
这件事的真相是什么?
【问题讨论】:
标签: c# static garbage-collection
他不知道他在说什么。非静态类中的静态成员不会阻止该类的实例被垃圾回收。
也就是说,静态变量可以在堆栈或堆上。垃圾收集没关系。重要的是类型的静态部分不与类型的实例一起存储。
【讨论】:
静态成员是 GC 的根。从静态引用的任何内容都将保持活动状态。静态引用是在静态类中还是在非静态类中是无关紧要的。
如果您有一个具有静态字段的非静态类,并且您有该类的实例,则静态字段没有很多实例 - 这是静态定义的一部分 - 它不是每个实例字段。所以类本身是否是静态的没有区别。
所以是的,静态引用通常是导致内存泄漏的原因,尤其是在适当的时候您还没有取消订阅的静态事件。将类更改为静态不会解决您的内存泄漏 - 您需要在它所引用的实例的生命周期结束时删除静态引用。这通常是通过 Dispose() 处理对象并让 Dispose 清理引用/事件订阅来完成的。
This 是了解更多关于 GC 工作原理、它如何识别垃圾以及它如何处理垃圾的好地方。以及决赛选手等等......
【讨论】:
你的朋友不正确。
静态方法的想法是没有该类的实例。所以垃圾收集不存在。
尝试将this 放在非静态类的静态方法中,看看会发生什么。
【讨论】: