基于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
方法呢?
答案 0 :(得分:6)
Component
类必须有一个调用this.Dispose()
的终结器,这会导致调用覆盖。
即使构造函数没有完成,也会运行终结器 - 这允许在构造函数之前分配的所有资源都无法清除。
答案 1 :(得分:1)
为什么要调用
Dispose
方法?
即使构造函数抛出异常,也会调用类的终结器。 finalizer for Component
来电Dispose()
:
~Component() {
Dispose(false);
}
由于覆盖Dispose(bool)
,如果构造函数抛出异常,则会调用覆盖。由于您的代码中存在这种可能性,因此我建议您确保this
和this._dispose
都不为空。