在析构函数中使用null条件运算符是不好的做法?

Geo*_*e K 4 .net c# vb6

我有一个带析构函数的类,我得到一个空引用异常,因为我有时会销毁变量null.

这是null条件运算符析构函数中的适当用法吗?

我甚至不确定这是否适合使用析构函数本身,因为它不是用于处理它所调用的实际对象而是用于处理它的变量.

~clsSAPSettings()
{

    mtbTemp?.Close();
}
Run Code Online (Sandbox Code Playgroud)

这段代码是从VB6转换而来的,所以我想弄清楚如何处理这个问题.欢迎任何信息.


编辑:该类mtbTemp属于implements,IDisposable没有 finaliser/desctructor.它只是关闭ORM模型中使用的连接.


对于任何人在详细解释后,我找到了一个很好的答案,正确使用IDisposable接口,它详细介绍了终结器的使用以及垃圾收集实际如何工作.

Dmi*_*nko 5

请不要在终结器中使用任何引用类型的字段:GC(垃圾收集器)收集它们的顺序是不可预测的,这就是为什么

 ~clsSAPSettings()
 {
     mtbTemp?.Close();
 }
Run Code Online (Sandbox Code Playgroud)

GC可以很好地执行代码,如下所示:

  1. 收集mtbTemp实例
  2. 开始收集this实例:
  3. 称呼~clsSAPSettings()
  4. 调用即调用收集(销毁)实例mtbTemp?.Close();的方法

你会遇到一个不稳定的难以发现的错误。看来您正在寻找一个IDisposable接口:

 public class clsSAPSettings: IDisposable {
   private MyTemp mtbTemp;

   ... 

   protected virtual void Dispose(bool disposing) {
     if (disposing) { 
        mtbTemp?.Close();

        GC.SuppressFinalize(this); 
     }
   }  

   public void Dispose() {
     Dispose(true);
   }

   //TODO: do you really want finalizer?
   ~clsSAPSettings() {
     Dispose(false);
   } 
 }
Run Code Online (Sandbox Code Playgroud)


Mar*_*ell 5

考虑:

~clsSAPSettings()
{    
    mtbTemp?.Close();
}
Run Code Online (Sandbox Code Playgroud)

这里的问题不是null条件用法.这本身并不存在任何问题.

最大的问题是在终结器中你不应该碰到任何其他物体.当终结者开火时,你的对象就是吐司.您不再对生命有任何保证mtbTemp,包括它是否已被垃圾收集,因此您不应该触摸它.它可能有用; 它可能会导致暂时的复活,或者它可能会崩溃.

这样做的正确的地方是IDisposable.Dispose.在Dispose方法中,这绝对是好的:

public void Dispose() // where your class : IDisposable
{    
    mtbTemp?.Close();
    mtbTemp = null;
}
Run Code Online (Sandbox Code Playgroud)

你可能根本不需要终结器.它们非常罕见.