在null
方法中将自定义对象设置为Nothing
(VB.NET中为Dispose()
)是否有意义?
这可以防止内存泄漏或无用吗?!
让我们考虑两个例子:
public class Foo : IDisposable
{
private Bar bar; // standard custom .NET object
public Foo(Bar bar) {
this.bar = bar;
}
public void Dispose() {
bar = null; // any sense?
}
}
public class Foo : RichTextBox
{
// this could be also: GDI+, TCP socket, SQl Connection, other "heavy" object
private Bitmap backImage;
public Foo(Bitmap backImage) {
this.backImage = backImage;
}
protected override void Dispose(bool disposing) {
if (disposing) {
backImage = null; // any sense?
}
}
}
答案 0 :(得分:24)
我个人倾向于;有两个原因:
Foo
(可能来自某个事件),任何下游对象(在这种情况下为Bitmap
)仍然可以被收集(在未来的某个时刻 - 每当GC感觉像这样); 可能这只是一个围绕非托管资源的浅层包装器,但每一点都有帮助。
IDisposable
是一个方便的“几乎杀死”开关 - 为什么不分离所有可用的东西?ObjectDisposedException
则抛出null
答案 1 :(得分:20)
Dispose()
的目的是允许清理垃圾收集器未处理的资源。对象由GC处理,因此在正常情况下实际上不需要将引用设置为null。
例外情况是,如果您希望调用者在此之后调用Dispose
并保留实例。在这种情况下,将内部引用设置为null是个好主意。然而,一次性实例通常同时被丢弃和释放。在这些情况下,它不会产生很大的不同。
答案 2 :(得分:4)
这只是无用的。我认为,在旧的COM / VB天中设置为NULL会减少您的引用计数。
.NET不适用。将bar设置为null时,不会破坏或释放任何内容。您只是将条指向的引用从您的对象更改为“null”。你的对象仍然存在(虽然现在,因为没有任何引用它,它最终将被垃圾收集)。除了极少数例外情况,在大多数情况下,如果您没有首先制作Foo IDisposable,就会发生同样的情况。
IDisposable的一个重要目的是允许您释放非托管资源,例如TCP套接字或SQL连接,或其他任何东西。这通常通过调用非托管资源提供的清理函数来完成,而不是通过将引用设置为“null”来完成。
答案 3 :(得分:1)
如果您想以某种方式阻止重置已使用的已拥有实例,这是有意义的。
如果将对一次性字段的引用设置为null,则可以保证不再使用这些实例。
使用自有的已处置实例不会导致ObjectDisposedException
或任何其他无效状态(如果不检查空值,则可能会获得NullReferenceException
)。
只要所有IDisposable
对象具有IsDisposed
属性和/或抛出ObjectDisposedException
(如果在处置后使用它们),这可能对您没有意义 - 有些可能违反此原则并将它们设置为null可以防止发生不必要的影响。
答案 4 :(得分:1)
在C#中,将对象设置为null只是释放对象的引用。
因此,理论上最好在C#中的Dispose-Method中释放对托管对象的引用,但仅限于GC在收集已处置对象之前收集引用对象的可能性。由于两者最有可能在同一次运行中收集,因此GC最可能会认识到,引用的对象仅由处置类型引用,因此两者都可以被收集。
此外,释放引用的需求非常小,因为如果同时处理该类,则您的一次性类的所有公共成员都应该抛出异常。因此,在处理引用的方法后,无法访问引用的对象。
答案 5 :(得分:1)
在 VB.NET 中有意义设置为Nothing
声明的 Private WithEvents
对象。
使用Handles
关键字的处理程序将以这种方式从这些对象中删除。
答案 6 :(得分:0)
dispose()
的目的是清理不受管理的资源。开发人员应该在dispose方法中释放TCP连接,数据库连接和其他数据库对象以及大量此类非托管资源。所以它真的很有意义。
答案 7 :(得分:0)
一般不需要设置为null。但是假设你的课程中有一个重置功能。</ p>
然后你可能会这样做,因为你不想两次调用dispose,因为某些Dispose可能无法正确实现并抛出System.ObjectDisposed异常。
private void Reset()
{
if(_dataset != null)
{
_dataset.Dispose();
_dataset = null;
}
//..More such member variables like oracle connection etc. _oraConnection
}