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

本文关键字:为什么 调用 Dispose 对象 我的 如果 | 更新日期: 2023-09-27 18:22:12

基于这篇文章,我在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在这一点上基本上为null,它会以NullReferenceException失败。

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

但是,如果构造函数抛出异常(我已经确认了),为什么要调用Dispose方法呢?

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

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

即使构造函数没有完成,终结器也会运行——这允许清理构造函数失败之前分配的所有资源。

为什么要调用Dispose方法?

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

    ~Component() {
        Dispose(false);
    }

由于您重写了Dispose(bool),因此如果构造函数抛出异常,就会调用您的重写。由于这在您的代码中是真实的可能性,我建议确保thisthis._dispose都不为空。