在析构函数中使用null条件运算符是不是很糟糕?

时间:2018-06-15 08:54:04

标签: c# .net vb6

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

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

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

~clsSAPSettings()
{

    mtbTemp?.Close();
}

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

修改:类mtbTemp属于实现IDisposable,但没有终结者/结构者。它只是关闭ORM模型中使用的连接。

对于任何人在详细解释后我找到了一个很好的答案Proper use of the IDisposable interface,它详细介绍了终结器的使用以及垃圾收集的实际工作方式。

3 个答案:

答案 0 :(得分:5)

考虑:

~clsSAPSettings()
{    
    mtbTemp?.Close();
}

这里的问题不是空条件用法。这并不能解决任何问题。

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

IDisposable.Dispose中执行此类操作的正确位置。在Dispose方法中,这绝对没问题:

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

你可能根本不需要终结器。他们难以置信罕见。

答案 1 :(得分:4)

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

的原因
 ~clsSAPSettings()
 {
     mtbTemp?.Close();
 }
GC可以很好地执行

代码,如下所示:

  1. 收集mtbTemp实例
  2. 开始收集this个实例:
  3. 致电~clsSAPSettings()
  4. 致电mtbTemp?.Close();,即调用收集(已销毁)实例的方法
  5. 并且您有不稳定很难找到错误。您似乎正在寻找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);
       } 
     }
    

答案 2 :(得分:3)

关闭流或其他非托管对象时,应使用public class Results extends AppCompatActivity { @Override protected void onResume() { super.onResume(); hideNavigationBar(); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_results); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); int headboyResult = prefs.getInt("headboy1", 0); TextView headBoy = (TextView) findViewById(R.id.headBoy); headBoy.setText(Integer.toString(headboyResult)); Button btn = (Button)findViewById(R.id.returnButton); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent back = new Intent(Results.this,MainPage.class); startActivity(back); } }); Button reset = (Button) findViewById(R.id.resetAll); reset.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // editor.putInt("headboy1", 0); } }); 模式,而不是析构函数。你永远不知道析构函数什么时候会发射。

关于在析构函数中使用null条件运算符:我发现运算符本身没有问题。我这样做是为了引用可能已被破坏或破坏的其他对象。