C# 将对象设置为null是否确定地处理对象?
我有一个奇怪的问题,我找不到一个明确的答案,即使有线程围绕着同一个问题 问题:如果我将一个对象设置为null,是否会导致dispose方法(已实现)被确定地调用?例如,在下面的代码中,通过将PricinGenEnvironment对象设置为null,Dispose会立即被调用吗?我知道如果没有调用Dispose,PricinGenEnvironment对象的终结器将在某个时候启动 代码: 谢谢,C# 将对象设置为null是否确定地处理对象?,c#,C#,我有一个奇怪的问题,我找不到一个明确的答案,即使有线程围绕着同一个问题 问题:如果我将一个对象设置为null,是否会导致dispose方法(已实现)被确定地调用?例如,在下面的代码中,通过将PricinGenEnvironment对象设置为null,Dispose会立即被调用吗?我知道如果没有调用Dispose,PricinGenEnvironment对象的终结器将在某个时候启动 代码: 谢谢, -Mike没有*方法确定垃圾收集器何时将收集对象并调用其终结器(并且,按照代码中的逻辑,Dispos
-Mike没有*方法确定垃圾收集器何时将收集对象并调用其终结器(并且,按照代码中的逻辑,
Dispose
方法)。
下面是一个很好的示例,说明了垃圾收集的不可预测性:
甚至当GC启动并收集第一代对象时,PricingEnvironment
的实例也会在第一次收集后继续存在,并被放在最终确定队列中
您应该通过显式调用dispose
或使用using
块来确定地处置对象
*实际上,您可以使用GC.Collect()强制它,但您不应该这样做。虽然计算机根据定义是确定性的,但当分配的内存被释放时,完全取决于语言实现的垃圾收集器。将其设置为null会减少分配内存的引用计数,但在任何情况下,当到达作用域结束时都会发生这种情况。不,不会 这样做:
public void Dispose()
{
// check if object has IDisposble implemented
IDisposable disposePricing = pricingEnvironment as IDisposable;
if (disposePricing!=null)
{
disposePricing.Dispose();
}
}
读一读我猜你把垃圾处理和垃圾收集混淆了 Dispose释放非托管资源(数据库连接或文件句柄) GC通过不再使用的对象释放占用的内存 Disposing是确定性的,因为它在调用Dispose时运行(无论是在
中使用块显式还是隐式)
垃圾收集本质上是不确定的。它在合适的时候运行。只有这样,它才能释放内存引用。
例如,如果GC运行的生成级别与对象当前所在的生成级别不同,则不会收集该对象
您可以通过调用GC.Collect()
显式运行GC,但请自问是否应该对GC进行二次猜测。在.NET中不能保证会调用终结器。垃圾收集器可能根本不调用它(例如,因为垃圾收集器根本不需要释放内存),并且在一个终结器抛出异常的情况下,其他终结器将不会执行(请参阅)。如果对对象调用SuppressFinalizer
,甚至可以抑制终结器
话虽如此,当然也不能保证立即调用终结器(它可能会在很久以后调用,或者根本不调用)
您应该显式调用Dispose
,或者使用using
-语句使用,以便正确地处理对象。作为安全网,您仍然可以从终结器调用Dispose
。事实上,这也是中的示例所展示的最佳实践
关于这个话题,雷蒙德·陈(Raymond Chen)的文章读得很好:
作为旁注,我想说的是,如果你处理的对象相对较小,你可以让垃圾收集器独自完成他的工作。我不知道这是否是一个好的实践,但我几乎只使用dispose()
关于文件或数据库连接…这并不是你的问题的重复,而是关于设置Null vs Dispose的一个非常好的答案-@Bartdude:好的实践表明,每当类实现IDisposable时,你都应该调用trhe Disposemethod@LuisFilipe>感谢您的见解:-)从现在起,我将在我的编码中制定规则!
public void Dispose()
{
// check if object has IDisposble implemented
IDisposable disposePricing = pricingEnvironment as IDisposable;
if (disposePricing!=null)
{
disposePricing.Dispose();
}
}