如果我的对象从未被构造,为什么要调用Dispose?

时间:2015-11-16 19:28:44

标签: c# dispose

基于this post,我在Windows窗体和IDisposable对象的组件之间创建了一个桥梁。它几乎看起来像这样:

namespace MyApp
{
    public class Disposer: Component
    {
        private readonly Action<bool> _dispose;

        public Disposer(Action<bool> disposeCallback)
        {
            if (disposeCallback == null)
                throw new ArgumentNullException(nameof(disposeCallback));

            this._dispose = disposeCallback;
        }

        protected override void Dispose(bool disposing)
        {
            this._dispose(disposing);
            base.Dispose(disposing);
        }
    }
}

到目前为止一切顺利。然后我创建了单元测试,包括一个用于构造函数参数的特定验证。

[TestMethod]
[ExpectedException(typeof(ArgumentNullException))]
public void Disposer_ShouldNotAllowNullActions()
{
    new Disposer(null);
}

这里有一个问题:不仅我的测试失败了,而且它实际上已经中止了。测试平台本身崩溃(ReSharper测试运行器)。通过挖掘我的Windows事件查看器,我可以看到正在调用Dispose()方法,并且由于此时this._dispose基本上为空,因此失败并显示NullReferenceException

我通过提供一个空的lambda作为默认值来解决这个问题。

但是如果构造函数抛出异常(我确认它会这样做),为什么调用Dispose方法呢?

2 个答案:

答案 0 :(得分:6)

Component类必须有一个调用this.Dispose()的终结器,这会导致调用覆盖。

即使构造函数没有完成,也会运行终结器 - 这允许在构造函数之前分配的所有资源都无法清除。

答案 1 :(得分:1)

  

为什么要调用Dispose方法?

即使构造函数抛出异常,也会调用类的终结器。 finalizer for Component来电Dispose()

    ~Component() {
        Dispose(false);
    }

由于覆盖Dispose(bool),如果构造函数抛出异常,则会调用覆盖。由于您的代码中存在这种可能性,因此我建议您确保thisthis._dispose都不为空。