2013-04-14 105 views
2

我有具有Dipose()方法这是IDisposable的正确用法吗?

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类通过Ftp

+0

什么是_ftp?你能否告诉我们你担心什么不工作? –

+0

为'_ftp'添加null检查可能是个好主意。 –

+0

'_ftp'是'edtFTPnet'的'FTPConnection'的一个实例,'_ftp'永远不会为空。 –

回答

3

我假设_ftp是一个IDisposable对象。如果是的话,它应该是足够做follwing:

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

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

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

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

+1

你应该添加密封到课堂上。 –

2

一般请参阅MSDN documentation for IDisposable interface

MSDN IDisposable.Dispose() documentation明确规定:

实现此方法时,确保所有占用的资源是 通过传播通过封闭层次的调用释放。对于 示例,如果对象A分配了对象B,并且对象B分配了对象C,则A的Dispose实现必须调用B上的Dispose, ,必须依次调用C上的Dispose。对象还必须调用 Dispose它的基类的方法,如果基类实现了 IDisposable。

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

有关您的设计警告的详细信息,请参阅MSDN CA1063: Implement IDisposable correctly

假设您的底层FTP实施不受管理,您应该应该也包括一个终结器,如果基础实现中尚不存在。该MSDN IDisposable.Dispose() documentation明确规定:

因为Dispose方法必须显式调用,对象是 实现IDisposable还必须实现一个终结处理 释放资源时,不叫处置。

也可以参考MSDN Object.FinalizeMSDN Implementing Finalize and Dispose to Clean Up Unmanaged Resources

如果有在你的产业链没有合适的终结的地方,也许这是你的警告的原因是什么?

也请注意(作为反例)微软建议消费者不应直接调用Dispose()MSDN using statement documentation状态:

通常,当您使用IDisposable的对象,还应当声明并 实例它在一个using语句。

消费者首选的方法是“用”的IDisposable资源,就像这样:

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

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

该模式还避免了对您的实例引用进行null检查的需求,因为实例已在该块的开始处构建。它还确保对象不能被重新分配(即使原始引用超出范围时也不会保护底层资源不被意外打开)。尽管如此,我认为你可以将这个模式(或等价的try/catch/finally)合并到你的继承/接口实现中,这是值得怀疑的。

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

3

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

您可能还想为该类添加一个Finalizer,如果使用该类的某个类由于某种原因未能正确处理它,则可以在该类中进行处置。

IDisposable interface文档中的编码示例非常完整并且评论良好。

+0

我以为是这样,因为它工作正常,但'Code Analysis'说我应该正确使用'IDisposable'。 “CA1063 \t正确实现IDisposable \t在'Ftp'上提供Dispose(bool)的可覆盖实现或将该类型标记为密封。对Dispose(false)的调用应仅清理本地资源。调用Dispose(true)应该清理托管资源和本地资源。“ –

+0

如果您只是封装另一个实现了IDisposable的类,那么最终定稿将是不适当的,因为如果有必要,该类将已经有一个终结器 –

+2

@BrunoKlein,you应该遵循这个指导,希望你可以把你的班级标记为密封 –