在.NET中使用后将对象设置为Null / Nothing

时间:2020-03-05 18:37:51  来源:igfitidea点击:

完成所有对象后,是否应该将所有对象设置为" null"(在VB.NET中为" Nothing")?

我知道,在.NET中,必须处置实现IDisposable接口的对象的任何实例以释放一些资源,尽管对象在处置后仍然可以是某种东西(因此,表单中的isDisposed属性),因此我认为它仍然可以驻留在内存中或者至少部分驻留吗?

我也知道,当一个对象超出范围时,它会被标记为可以进行下一次垃圾收集器的收集(尽管这可能需要一些时间)。

因此,考虑到这一点,将其设置为" null"将加快系统释放内存的速度,因为它不必确定它已不在范围内,并且它们是否会产生不良影响?

MSDN文章从不在示例中执行此操作,目前我无法执行此操作
看到危害。但是,我遇到了多种意见,因此任何评论都是有用的。

解决方案

回答

某些对象假设使用.dispose()方法,该方法强制将资源从内存中删除。

回答

不,不要为空对象。我们可以查看http://codebetter.com/blogs/karlseguin/archive/2008/04/27/foundations-of-programming-pt-7-back-to-basics-memory.aspx了解更多信息,但需要进行设置为null不会执行任何操作,除非弄脏代码。

回答

唯一应将变量设置为null的情况是,变量不会超出范围并且不再需要与之关联的数据。否则没有必要。

回答

还:

using(SomeObject object = new SomeObject()) 
{
  // do stuff with the object
}
// the object will be disposed of

回答

在某些情况下,对空引用有意义。例如,当我们按照合同约定编写一个集合(如优先级队列)时,在客户端将它们从队列中删除后,我们不应该为客户端保留这些对象。

但是,这种情况仅适用于寿命长的收藏。如果队列不能幸免于创建该函数的末尾,那么它的重要性就小得多。

总的来说,我们真的不应该打扰。让编译器和GC进行工作,以便我们可以完成工作。

回答

Karl绝对正确,使用后无需将对象设置为null。如果一个对象实现了" IDisposable",只需确保在处理完该对象后调用" IDisposable.Dispose()"(包装在" try" .." finally"中,或者在" using()"块中) )。但是,即使我们不记得调用Dispose(),对象上的finaliser方法也应该为我们调用Dispose()

我认为这是一种很好的治疗方法:

挖掘IDisposable

还有这个

了解IDisposable

试图再次猜测GC及其管理策略没有任何意义,因为它是自调整的并且是不透明的。在此处,关于点网岩石上的Jeffrey Richter的内部工作方式进行了很好的讨论:Windows Memory Model和Windows内存模型上的Jeffrey Richter
里希特斯通过第20章对CLR的书进行了很好的处理:

回答

通常,使用后无需将对象为空,但是在某些情况下,我认为这是一种好习惯。

如果一个对象实现IDisposable并存储在一个字段中,我认为最好将其为null,以避免使用已处置的对象。下列错误可能很痛苦:

this.myField.Dispose();
// ... at some later time
this.myField.DoSomething();

最好在处理完该字段后使该字段为空,然后在再次使用该字段的行上获取一个NullPtrEx。否则,我们可能会遇到一些神秘的错误(具体取决于DoSomething所做的事情)。

回答

如果我们觉得需要清空变量,则可能是代码结构不够严密。

有多种方法可以限制变量的范围:

正如史蒂夫·特兰比(Steve Tranby)所述

using(SomeObject object = new SomeObject()) 
{
  // do stuff with the object
}
// the object will be disposed of

同样,我们可以简单地使用大括号:

{
    // Declare the variable and use it
    SomeObject object = new SomeObject()
}
// The variable is no longer available

我发现使用不带任何"标题"的大括号可以真正清除代码并使其更易于理解。

回答

完成对象操作后避免将其设置为null的另一个原因是,它实际上可以使它们存活更长的时间。

例如

void foo()
{
    var someType = new SomeType();
    someType.DoSomething();
    // someType is now eligible for garbage collection         

    // ... rest of method not using 'someType' ...
}

将允许在调用" DoSomething"之后将someType引用的对象进行GC处理,但是

void foo()
{
    var someType = new SomeType();
    someType.DoSomething();
    // someType is NOT eligible for garbage collection yet
    // because that variable is used at the end of the method         

    // ... rest of method not using 'someType' ...
    someType = null;
}

有时可能会使对象保持活动状态,直到方法结束。 JIT通常会将分配优化为null,因此代码的两个位最终都是相同的。

回答

还要看一下这篇文章:http://www.codeproject.com/KB/cs/idisposable.aspx

在大多数情况下,将对象设置为null无效。唯一应该确定的是,如果使用的是"大对象",它的大小大于84K(例如位图)。