您是否需要处理对象并将其设置为null,或者当它们超出作用域时,垃圾收集器将清理它们?
当前回答
A little late to the party, but there is one scenario that I don't think has been mentioned here - if class A implements IDisposable, and exposes public properties that are also IDisposable objects, then I think it's good practice for class A not only to dispose of the disposable objects that it has created in its Dispose method, but also to set them to null. The reason for this is that disposing an object and letting it get GCed (because there are no more references to it) are by no means the same thing, although it is pretty definitely a bug if it happens. If a client of Class A does dispose its object of type ClassA, the object still exists. If the client then tries to access one of these public properties (which have also now been disposed) the results can be quite unexpected. If they have been nulled as well as disposed, there will be a null reference exception immediately, which will make the problem easier to diagnose.
其他回答
总是调用dispose。不值得冒这个险。大型托管企业应用程序应该受到尊重。不能做任何假设,否则它会反过来咬你一口。
别听她的。
很多对象实际上并没有实现IDisposable,所以你不必担心它们。如果他们真的超出了范围,他们将自动被释放。此外,我从来没有遇到过必须将某些内容设置为null的情况。
可能发生的一件事是,很多物体都可以保持打开状态。这将极大地增加应用程序的内存使用。有时很难判断这究竟是内存泄漏,还是您的应用程序只是在做很多事情。
内存配置文件工具可以帮助解决这类问题,但它可能很棘手。
此外,始终取消对不需要的事件的订阅。还要注意WPF绑定和控件。不常见的情况,但我遇到了这样的情况,我有一个WPF控件被绑定到一个底层对象。底层对象很大,占用了大量内存。WPF控件正在被一个新的实例所取代,而旧的实例由于某种原因仍然存在。这导致了一个大的内存泄漏。
在后台,代码写得很糟糕,但关键是你要确保没有使用的东西超出了范围。这需要很长时间才能用内存分析器找到,因为很难知道内存中的哪些东西是有效的,哪些不应该在那里。
通常,不需要将字段设置为null。然而,我总是建议丢弃非托管资源。
根据我的经验,我还建议你这样做:
如果不再需要,则取消订阅事件。 如果不再需要,将持有委托或表达式的任何字段设置为空。
我遇到过一些很难发现的问题,这些问题都是由于没有遵循上述建议而直接导致的。
Dispose()是执行此操作的一个好地方,但通常越快越好。
一般来说,如果存在对某个对象的引用,垃圾收集器(GC)可能要多花几代时间才能确定该对象不再使用。在此期间,对象始终保留在内存中。
这可能不是一个问题,直到你发现你的应用程序正在使用比你预期的更多的内存。当发生这种情况时,连接内存分析器来查看哪些对象没有被清理。将引用其他对象的字段设置为null并在处理时清除集合可以真正帮助GC确定可以从内存中删除哪些对象。GC将更快地回收使用的内存,使您的应用程序的内存需求更少,更快。
如果对象实现了IDisposable,那么是的,你应该释放它。对象可能挂在本地资源(文件句柄、操作系统对象)上,否则这些资源可能不会立即释放。这可能导致资源短缺、文件锁定问题和其他本来可以避免的微妙错误。
参见在MSDN上实现一个Dispose方法。
我也得回答。 JIT从对变量使用情况的静态分析中生成表和代码。 这些表项是当前堆栈帧中的“GC-Roots”。随着指令指针的前进,这些表项变得无效,因此准备进行垃圾收集。 因此:如果它是一个作用域变量,你不需要将它设置为null - GC将收集该对象。 如果它是一个成员或静态变量,则必须将其设置为null
当对象不再被使用并且垃圾回收器认为合适时,对象将被清理。有时,您可能需要将一个对象设置为null以使其超出作用域(例如您不再需要其值的静态字段),但总体而言,通常不需要将其设置为null。
关于处置对象,我同意@Andre的观点。如果对象是IDisposable的,那么在不再需要它时释放它是个好主意,特别是当对象使用非托管资源时。不处理非托管资源将导致内存泄漏。
一旦程序离开using语句的作用域,就可以使用using语句自动处理对象。
using (MyIDisposableObject obj = new MyIDisposableObject())
{
// use the object here
} // the object is disposed here
其功能等价于:
MyIDisposableObject obj;
try
{
obj = new MyIDisposableObject();
}
finally
{
if (obj != null)
{
((IDisposable)obj).Dispose();
}
}
推荐文章
- 什么是.NET程序集?
- 字符串不能识别为有效的日期时间“格式dd/MM/yyyy”
- 函数应该返回空对象还是空对象?
- 如何转换日期时间?将日期时间
- 如何在c#中连接列表?
- 在c#中引用类型变量的“ref”的用途是什么?
- 防止在ASP中缓存。NET MVC中使用属性的特定操作
- 转换为值类型'Int32'失败,因为物化值为空
- c#中有任何连接字符串解析器吗?
- 在Linq中转换int到字符串到实体的问题
- 是否可以动态编译和执行c#代码片段?
- 创建自定义MSBuild任务时,如何从c#代码获取当前项目目录?
- MSBuild路径
- c#和Java的主要区别是什么?
- 在c#中创建一个特定时区的DateTime