2

假设我有一个包含两个字段的类,每个字段都包含一次性对象。

    class C : IDisposable {

            private IDisposable thing1 = new Thing1();
            private IDisposable thing2 = new Thing2();

               ... IDisposable implementation ...
    }

当创建一个类的实例时C Thing1会被创建,然后Thing2. 但是,如果在构造时发生异常Thing2,它将不会被创建,并且类的实例C也不会完成创建。实例化类的代码C没有对部分构造的引用来C调用Dispose它,所以我们留下了一个Thing1永远不会被释放的实例。

什么是最好的分辨率?

4

2 回答 2

3

您可以将初始化代码移至构造函数,然后将整个构造函数包装在一个try/catch块中,该块处理所有拥有的对象并重新引发异常。

于 2013-06-02T03:56:10.967 回答
1

在 C++/CLI 中,单个声明可以指定应如何定义、初始化和清理字段。在 vb.net 中,可以设计一个基类,以便子类也可以这样做,例如

Dim MyBitmap as Bitmap = Acquire(new Bitmap(Params.FileName))

whereParams是一个对象,其中FileName存储了一些构造函数参数(如 )。该Acquire方法(在基类中定义)会将新创建的引用添加到IDisposable构造函数抛出时应清理的事物列表中。

不幸的是,C# 不支持这两种模式。最接近的可能是定义一些静态方法,这些方法使用ThreadStatic字段来跟踪创建的对象,但这有点令人讨厌。在实践中,最好的方法可能是定义Dispose以便正确处理部分构造的对象,并让每个构造函数都包含如下代码:

bool success = false;
try
{
  ...initialize stuff
  success = true;
}
finally
{
  if (!success)
    Dispose();
}

请注意,由于Dispose()是虚拟的,它可能会被多次调用。此外,由于子类Dispose方法可能在子类构造函数没有运行的情况下被调用,因此每Dispose一层都需要为这种可能性做好准备。

于 2013-06-03T17:24:06.013 回答