【问题标题】:Static Method on object inheriting Disposable对象继承 Disposable 的静态方法
【发布时间】:2017-11-07 17:12:01
【问题描述】:
我最近继承了一个遇到内存泄漏的 asp.net 项目。在我的调查中,我注意到有很多实现 IDisposable 的自定义类,但它们在调用时没有使用“使用”。我一直在解决这些问题,但我很好奇的一个用例是将静态方法放在类上。像这样的:
public class ImDisposable : IDisposable{
public static GetList(string search){
//doStuff
}
//implement IDisposable
}
public class UseDisposable{
public void GetList(string search){
var list = ImDisposable.GetList(search);
//do stuff
}
}
我从来没有见过这样的事情,我很好奇 GC 是如何处理这种情况的。谢谢。
【问题讨论】:
标签:
c#
asp.net
static
garbage-collection
【解决方案1】:
静态方法不依赖于任何特定实例,因此它们不应该能够访问可能占用非托管资源的类的实例成员。
在考虑资源处置时,您无需考虑它们
在相关的说明中,方法的存在也与 IDisposable 无关。它本身并不处理“方法”,它处理类的实例可能使用的非托管资源。 (比如打开的文件流)
【解决方案2】:
您可能会混淆内存泄漏和垃圾收集...仅仅因为您没有调用Dispose() 并不意味着您会有泄漏。在以下情况下会发生泄漏:
(1) 你没有释放的类有一个非托管资源的句柄,例如一个文件流。从理论上讲,如果一个类实现了 IDisposable,它就有非托管资源,但我已经看到了足够多的空 dispose 方法,我已经厌倦了。 IE。对于静态类/成员,除非您有需要处理的静态变量,否则这不是您的内存泄漏。
此外,无论您实例化多少个类,静态成员都只会有一个实例,并且当没有创建新实例时,您不会真正发生泄漏。
(2) 当您不需要/不打算这样做时,您可以保留对象引用...很好的例子是事件侦听器,尤其是那些连接为 lambda 的事件侦听器。不在数据库连接上调用 Dispose() 也被视为泄漏,即使 Dispose() 只是将连接返回到连接池。
还要记住,不断增长的内存占用不一定是泄漏。垃圾收集仅在 .NET 运行时认为有必要时执行...如果仍有大量可用内存,则无需 GC。
高度简化的概述;我主要是说static 与您的内存泄漏无关。有一篇关于确定内存泄漏的好文章here
【解决方案3】:
你的问题有点含糊。
您可以查看 Richter 的 CLR via C# 一书,了解有关垃圾收集的说明。尽管我的感觉是您的问题更多是关于非静态类中的静态方法与垃圾收集器之间的交互。上面提到的书也涵盖了这一点。
通常,分配资源的静态方法的行为与分配资源的非静态方法类似。但是,IDisposable 接口将对类的实例进行操作。因此,您的
静态GetList(..)
方法不应使用需要 IDisposable 实现来释放的资源。