2

我有一个 FTP 类,它有一个Dipose()方法

public class Ftp : IFtp
    {
        //other methods, properties and fields

        public void Dispose()
        {
            if (_ftp.IsConnected)
                _ftp.Close();

            _ftp.Dispose();
            _ftp = null;
        }
    }

这是我用来访问Ftp类的接口

public interface IFtp : IDisposable
    {
        //other methods signatures
        void Dispose();
    }

这是处理所使用的内容的适当且实用的方式Ftp吗?

4

3 回答 3

3

这适用于该类的常规使用。但是,您应该_ftp在开始访问它之前检查引用是否为空。通常的做法是您应该能够Dispose多次调用该方法而不会造成任何伤害。

您可能还想在类中添加一个终结器,您可以在其中处理它,以防使用该类的人由于某种原因无法正确处理它。

IDisposable接口文档中的编码示例非常完整并且注释很好。

于 2013-04-14T01:19:40.400 回答
3

我认为 _ftp 是一个 IDisposable 对象。如果是这样,那么执行以下操作就足够了:

public class Ftp : IFtp
{
    //other methods, properties and fields

    public void Dispose()
    {
        _ftp.Dispose();    
    }
}

public interface IFtp : IDisposable
{
    //other methods signatures    
}

Dispose()也就是说,如果你的接口继承自,你不需要重新指定方法(在你的接口中) IDisposable,因为它已经在IDisposable.

于 2013-04-14T01:19:58.897 回答
2

接口一般参考MSDN 文档。IDisposable

MSDNIDisposable.Dispose()文档特别指出:

实现此方法时,请确保通过在包含层次结构中传播调用来释放所有持有的资源。例如,如果一个对象 A 分配了一个对象 B,而对象 B 分配了一个对象 C,那么 A 的 Dispose 实现必须调用 B 上的 Dispose,而 B 又必须调用 C 上的 Dispose。一个对象还必须调用其基类的 Dispose 方法如果基类实现 IDisposable,则为类。

...这就是你在做什么。

有关您的设计警告的详细信息,请参阅MSDN CA1063:正确实现 IDisposable

假设您的底层 FTP 实现不受管理,您还应该包括一个终结器(如果基础实现中还没有终结器)。MSDNIDisposable.Dispose()文档特别指出:

因为必须显式调用 Dispose 方法,所以实现 IDisposable 的对象还必须实现终结器以在未调用 Dispose 时处理释放资源。

另请参阅MSDNObject.FinalizeMSDN 实施 Finalize 和 Dispose 以清理非托管资源

如果您的继承链中某处没有适当的终结器,也许这就是您发出警告的原因?

另请注意(作为反例)Microsoft 建议消费者不要Dispose()直接致电。 MSDNusing声明文档指出:

通常,当您使用 IDisposable 对象时,您应该在 using 语句中声明和实例化它。

消费者的首选方法是“使用”IDisposable资源,如下所示:

   using (FTP myDisposableFTP = new FTP()) {
     ...
   }

这基本上是“语法糖”,以确保Dispose()在您完成使用一次性资源(即块的末尾)时调用该方法,或者重要的是,如果块发生using异常。using

此模式还避免了null检查实例引用的要求,因为实例是在块的开头构造的。它还确保无法重新分配对象(保护底层资源不被意外打开,即使您的原始引用超出范围)。

但是我认为您能否将这种模式(或等效的 try/catch/finally)合并到您的继承/接口实现中是值得怀疑的。

所以是的,调用该Dispose()方法在功能上是可以的,只要你记得在所有需要它的情况下调用它(例如在你的异常处理中),或者你将它重新暴露给你的消费者以正确处理“包装”IDisposable实现的一部分。但是,如果您的资源是非托管的,您还应该添加一个终结器。

于 2013-04-14T01:16:24.867 回答