C# 在.NET中使用后将对象设置为Null/Nothing
完成所有对象后,是否应将它们设置为C# 在.NET中使用后将对象设置为Null/Nothing,c#,.net,vb.net,memory-management,null,C#,.net,Vb.net,Memory Management,Null,完成所有对象后,是否应将它们设置为null(Nothing,在VB.NET中) 我知道在.NET中,必须处理实现IDisposable接口的对象的任何实例,以释放一些资源,尽管对象在被处理后仍然可以是某种东西(因此isDisposed属性在表单中),所以我假设它仍然可以驻留在内存中,或者至少部分驻留在内存中 我还知道,当一个对象超出作用域时,它会被标记为准备收集,以便下一次通过垃圾收集器(尽管这可能需要时间) 因此,考虑到这一点,将其设置为null会加快系统释放内存的速度,因为它不必计算出它不再
null
(Nothing
,在VB.NET中)
我知道在.NET中,必须处理实现IDisposable
接口的对象的任何实例,以释放一些资源,尽管对象在被处理后仍然可以是某种东西(因此isDisposed
属性在表单中),所以我假设它仍然可以驻留在内存中,或者至少部分驻留在内存中
我还知道,当一个对象超出作用域时,它会被标记为准备收集,以便下一次通过垃圾收集器(尽管这可能需要时间)
因此,考虑到这一点,将其设置为null
会加快系统释放内存的速度,因为它不必计算出它不再在范围内,并且它们是否有任何不良副作用
MSDN文章从来没有在示例中这样做过,目前我做不到这一点
看到危害了吧。然而,我遇到了各种各样的观点,因此任何注释都是有用的。一些对象假设使用
.dispose()
方法强制从内存中删除资源。否不允许对象为空。您可以查看更多信息,但将内容设置为null不会起任何作用,只会弄脏您的代码。您应该将变量设置为null的唯一时间是当变量未超出范围并且您不再需要与其关联的数据时。否则就没有必要了。另外:
using(SomeObject object = new SomeObject())
{
// do stuff with the object
}
// the object will be disposed of
在某些情况下,空引用是有意义的。例如,当您编写一个集合(如优先级队列)时,根据您的约定,在客户机将这些对象从队列中删除之后,您不应该为客户机保持这些对象的活动状态 但这类东西只在长寿命的收藏品中起作用。如果队列不能在创建它的函数结束后继续存在,那么它就不那么重要了
总的来说,你真的不应该麻烦。让编译器和GC完成它们的工作,这样您就可以完成自己的工作。Karl是绝对正确的,使用后不需要将对象设置为null。如果一个对象实现了
IDisposable
,只需确保在处理完该对象后调用IDisposable.Dispose()
(包装在中,最后尝试。或者使用()
块)。但是,即使您不记得调用Dispose()
,对象上的finalizer方法也应该为您调用Dispose()
我认为这是一种很好的治疗:
还有这个
试图对GC及其管理策略进行二次猜测是没有任何意义的,因为它是自调优和不透明的。与Jeffrey Richter在Dot Net Rocks上就内部工作进行了很好的讨论:以及
Richters的书第20章有一个很好的处理方法:一般来说,使用后不需要空对象,但在某些情况下我发现这是一个很好的做法
如果一个对象实现IDisposable并存储在一个字段中,我认为最好将其设为null,以避免使用disposed对象。以下类型的错误可能会令人痛苦:
this.myField.Dispose();
// ... at some later time
this.myField.DoSomething();
最好在处理字段后将其置零,并在再次使用该字段的行处获得一个null ptrex。否则,您可能会遇到一些隐藏的错误(具体取决于DoSomething的作用)。如果您觉得需要null
变量,那么代码的结构可能不够紧密
有许多方法可以限制变量的范围:
如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的原因是,它实际上可以让它们保持更长的生存时间
e、 g
将允许在调用“DoSomething”后对someType引用的对象进行GC'd,但是
有时可能会使对象保持活动状态,直到方法结束。因此,这两个代码位最终都是相同的。也可以看看这篇文章:
在大多数情况下,将对象设置为null没有效果。只有在使用大于84K的“大对象”(如位图)时,才应确保这样做。这种“使用后无需将对象设置为空”并不完全准确。在处理变量后,有时需要将其设为NULL
是的,当您完成操作时,您应该始终调用.Dispose()
或.Close()
。无论是文件句柄、数据库连接还是一次性对象
与此不同的是懒散的实际模式
假设我拥有并实例化了A类
的ObjA
<代码>A类
有一个名为PropB
的公共属性,属于B类
在内部,PropB
使用私有变量\u B
并默认为null。当使用PropB.Get()
时,它会检查\u PropB
是否为空,如果为空,则会打开将B
实例化为\u PropB
所需的资源。然后返回\u PropB
根据我的经验,这是一个非常有用的技巧
如果您以某种方式重置或更改A,而\u PropB
的内容是A
以前的值的子项,则需要对其进行处理并清空\u PropB
,以便LazyLoad可以在代码需要时重置以获取正确的值
如果您只执行\u PropB.Dispose()
,并且在期望LazyLoad的null检查成功后不久,它将不会为null,您将看到过时的数据。实际上,您必须在Dispose()
ju之后将其置空
void foo()
{
var someType = new SomeType();
someType.DoSomething();
// someType is now eligible for garbage collection
// ... rest of method not using 'someType' ...
}
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;
}
private void Reset()
{
if(_dataset != null)
{
_dataset.Dispose();
_dataset = null;
}
//..More such member variables like oracle connection etc. _oraConnection
}