我正在为我的公司清理一些C#代码,而且我注意到的一件事是构建此应用程序的承包商将对象引用设置为null。
示例:
get {
Object o = new Object(); // create a new object that is accessed by the reference 'o'
try {
// Do something with the object
}
finally {
o = null; // set the reference to null
}
}
据我所知,创建的对象仍然存在。有可能现在无法访问它,具体取决于是否有任何其他引用,但它将一直存在,直到GC到来并清理它。
有没有理由在finally块中有这个?在任何情况下,这可能会产生广告中的内存泄漏吗?
谢谢!
答案 0 :(得分:14)
这取决于范围。
在您给出的示例中,o
仅在属性范围内定义。所以它将毫无用处。但是,说o
属于班级范围。然后它可能有意义来表示o
的状态。
目前,不需要它。
答案 1 :(得分:6)
如果目的是让GC尽快收集对象,那么它完全没用。
如果在o
块之后的任何地方都没有使用try
引用的对象,那么它将在上次使用后立即被选中进行收集(即,在变量o
之前进行收集超出范围,并且在它到达finally
块之前。
在相关说明中,请参阅Lippert的Construction Destruction。
答案 2 :(得分:-1)
我认为至少有两个原因可以做到这一点。首先,使用此模式始终有助于捕获由重用变量引起的错误(即,如果这是更大的代码序列的一部分,则变量名称“o”可能在执行后期保留不同的对象)。通过显式赋值null,如果您稍后尝试使用同一个对象,则会确保此类代码导致错误(假设您意外地将构造函数注释为较大块的一部分)。
其次,分配null可确保该对象可能由GC收集。虽然对类变量更重要,但即使局部变量也可能受益。由于对象不是通过赋值读取,因此任何现有的优化都不应该受到包含赋值的影响(不管它是多么不必要)。类似地,赋值本身可能完全被优化掉(如果对象永远不会被随后访问),但由于这些优化都是编译器的范围,因此使用此结构允许更早地收集不包括的备用编译模型的可能性这样的优化。
这需要比我拥有的C#语言规范更熟悉,但我怀疑他们没有声明在最后一次访问后必须必须分配对象。基于单个编译器或一组编译器的当前操作进行这种假设可以在以后尝试移植到不遵循相同原则的环境时导致更多工作。
对于潜在的内存泄漏,假设GC工作正常,并且对象不需要特殊处理,应该没有问题 - 实际上你是专门删除对未使用内存的潜在引用,可能允许它回收。对于有特殊处理要求的物体,我希望它们可以在同一个地方处理。