我有一个带有析构函数的类,我从中得到了一个空引用异常,因为我销毁的变量有时是null
。
在析构函数中使用空条件运算符合适吗?
我甚至不确定这是否是析构函数本身的恰当使用,因为它不是用来处理被调用的实际对象的,而是它的一个变量。
~clsSAPSettings()
{
mtbTemp?.Close();
}
这段代码是从VB6转换而来的,所以我正在尝试弄清楚如何处理这个问题。欢迎提供任何信息。
编辑: mtbTemp
所属的类实现了IDisposable
,但没有终结器/描述器。它只是关闭了ORM模型中使用的连接。
对于任何经过详细解释的人来说,我找到了一个很好的答案,Proper use of the IDisposable interface,它详细介绍了终结器的使用以及垃圾收集是如何工作的。
发布于 2018-06-15 17:04:15
请不要在终结器中使用任何引用类型的字段: GC (垃圾收集器)收集它们的顺序是不可预测的,这就是为什么
~clsSAPSettings()
{
mtbTemp?.Close();
}
GC可以很好地执行如下代码:
mtbTemp
instancethis
instance: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);
}
}
发布于 2018-06-15 17:05:33
考虑一下:
~clsSAPSettings()
{
mtbTemp?.Close();
}
这里的问题不是null条件用法。这本身并不会带来任何问题。
最大的问题是,在终结器中,你不应该接触任何其他的对象。当终结器触发时,你的对象就结束了。你不再对mtbTemp
的生命周期有任何保证,包括它是否已经被垃圾回收,所以你的不应该接触它。它可能会起作用;它可能会导致暂时的复活,或者它可能会可怕地崩溃。
这样做的正确位置是在IDisposable.Dispose
中。在Dispose
方法中,这绝对没问题:
public void Dispose() // where your class : IDisposable
{
mtbTemp?.Close();
mtbTemp = null;
}
你可能根本不需要终结器。它们非常稀有。
发布于 2018-06-15 16:56:02
在关闭流或其他非托管对象时,应使用Dispose
模式,而不是析构函数。你永远不会知道那个析构函数什么时候会触发。
关于析构函数中空条件运算符的使用:我认为运算符本身没有问题。我会引用其他可能已经被析构或正在销毁的对象。
https://stackoverflow.com/questions/50872151
复制相似问题