我有一个带有析构函数的类,我得到 null引用异常,因为我销毁的变量有时是null
。
这是 null条件运算符在析构函数中的适当用法吗?
我甚至不确定这是否是对析构函数本身的适当使用,因为它不用于处理它所调用的实际对象,而是用于处理它的变量。
~clsSAPSettings()
{
mtbTemp?.Close();
}
此代码是从VB6转换而来的,所以我试图弄清楚如何处理这个问题。欢迎任何信息。
修改:类mtbTemp
属于实现IDisposable
,但没有终结者/结构者。它只是关闭ORM模型中使用的连接。
对于任何人在详细解释后我找到了一个很好的答案Proper use of the IDisposable interface,它详细介绍了终结器的使用以及垃圾收集的实际工作方式。
答案 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可以很好地执行代码,如下所示:
mtbTemp
实例this
个实例:~clsSAPSettings()
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);
}
}
答案 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条件运算符:我发现运算符本身没有问题。我这样做是为了引用可能已被破坏或破坏的其他对象。