如果一个成员实现了IDisposable接口,那么我们需要实现IDisposable接口吗?

7
我认为是这样的。但是看一下ASP.NET中的内置类:

我认为是这样的。但是看一下 ASP.NET 中的内置类:

public sealed class HttpPostedFile
{
    public Stream InputStream { get; }   // Stream implements IDisposable
    // other properties and methods
}

假设我有一个名为fileHttpPostedFile实例。由于没有明确调用的Dispose方法,所以file.InputStream.Dispose()直到它被销毁才会被调用,这与IDisposable的原始意图相违背。我认为正确的实现应该包含标准的IDisposable实现。因此,如果其中一个成员实现了IDisposable,则该类也需要实现它。
你有什么看法?这似乎有点复杂。
3个回答

10
一般来说,如果您拥有属性所代表的资源,则应实现 IDisposable - 请参见此问题的讨论。
我认为由于HttpPostedFile是在处理HTTP请求期间实例化的,它不拥有流,因此不需要进行释放。当HTTP请求处理完成时,该流将被释放。

哦,看起来我的问题是一个重复的问题。谢谢提供链接。我会在1分钟内接受这个答案。 - Cheng Chen
通常情况下,只有在你是构造该对象的人时,才需要负责处理对象。+1 - MattDavey

2

如果你的类创建了一个或多个IDisposable对象并保留其唯一的引用,则你的类几乎肯定应该实现IDisposable并且释放它所创建的IDisposable对象。如果一个或多个IDisposable对象将传递到你的类的构造函数中,则需要考虑一些情况:

  1. 你的创作者可能希望在你使用完之后继续使用IDisposable,并且肯定会知道何时不再需要它(你的类语义会让他知道你已经使用完了)。
  2. 当你使用完之后,你的创作者将不想再使用IDisposable,并且可能不知道何时使用完它。
  3. 你的类可能在与(1)相对应的某些情况下使用,在某些情况下与(2)相对应,但是你的创作者会提前知道适用哪种情况。
  4. 你的创作者无法预测在你使用完之后是否还需要继续使用该对象。
对于情况#1,您无需实现IDisposable,尽管为将来可能出现的其他情况,实现一个什么也不做的IDisposable处理程序并让使用者使用它可能不是个坏主意。
对于情况#2,您的对象应该拥有IDisposable的所有权,并在完成后Dispose它。我不太喜欢对象无条件地拥有IDisposable的所有权;我更喜欢实现第3种方式。

处理 #3 有两种方法。 我更喜欢的一种是你的对象需要带一个参数(布尔值或枚举类型),以及 IDisposable,指示它是否应该拥有这个 IDisposable。 你的类无条件地实现了 IDisposable;该实现会处理拥有的任何对象,但不会处理没有拥有的对象。 另一种方法是,有两个子类共用一个基类 - 一个子类实现了 IDisposable,而另一个则没有。 我更喜欢前者,因为它允许添加一个方法来替换一个 IDisposable 为一个新的(可能拥有也可能不拥有)。例如,如果我要实现一个具有 Image 属性的控件,我会有一个 SetImage 方法,其中有一个参数指定控件是否拥有传入的图像;该方法将处理旧图像(如果它拥有它),然后可以拥有或者不拥有新图像。

bool OwnMyImage;
Image MyImage;
void SetImage(Image NewImage, bool TakeOwnership)
{
    IDisposable oldDisposable; // Could reuse one variable for multiple IDisposables
    if (OwnMyImage)
    {
        oldDisposable = Threading.Interlocked.Exchange(MyImage, null);
        if (oldDisposable != null)
        {
            oldDisposable.Dispose();
        }
    }
    OwmMyImage = TakeOwnership;
    MyImage = NewImage;
}

场景 #4 很复杂;最好的处理方式可能是让你的对象通过引发 Disposed 事件来实现 IDisposable。你的创建者可以使用该事件来执行 Dispose 对象,如果你是最后一个使用它的人,或者调整标志或计数器,以便其他代码知道对象不应该被留下未处理。


0

这要看情况。

Stream 也可以由 TextStream 实现(可能基于 StringBuilder),因此不需要任何非托管资源。

HttpPostedFile 可能根本不使用任何非托管资源,因此可以安全地推迟析构,直到垃圾回收器认为合适为止。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接