在处理类实例时,是否需要显式处理其所有IDisposable成员?

我有一个类,它具有SqlConnection类型的属性。 SqlConnection实现了IDisposable 。 我有以下问题:

  1. 我的类是否也应该实现IDisposable ,因为它具有IDisposable类型的属性?
  2. 如果是,我在处理类的实例时是否需要显式处理属性? 例如

     public class Helper : IDisposable { // Assume that it's ANY OTHER IDisposable type. SqlConnection is just an example. public SqlConnection SqlConnection { get; set; } public void Dispose() { if (SqlConnection!= null) { SqlConnection.Dispose(); } } } 

注意:我知道在实现IDisposable需要遵循一个模式,但我的问题非常具体到上面提到的情况。

取决于 。 如果你的类创建拥有 IDisposable必须处理它(所以,两个答案都是“是” )。 如果你的class级只使用 IDisposable它就不能处理它(所以第一个答案通常是“no”而第二个答案是“no” )。

在你的情况下,似乎是Helper

  public class Helper { // Note, that you can assign any arbitrary Connection via this property public SqlConnection SqlConnection { get; set; } .... } 

只是使用 SqlConnection (因为它提供“set”)的方式就像

 // It's not helper that owns SqlConnection using (SqlConnection con = new SqlConnection(...)) { ... // helper just uses Connection, so helper must not dispose it Helper helper = new Helper() { SqlConnection = con; }; ... } 

所以它不能处理连接。 相反,这样的一类

 public class Helper: IDisposable { private SqlConnection m_SqlConnection; // Note the absence of public "set" public SqlConnection SqlConnection { get { return m_SqlConnection; } } ... } 

拥有它的SqlConnection因此它负责处理它:

 using (Helper helper = new Helper(...)) { ... // it's helper that owns SqlConnection SqlConnection con = helper.SqlConnection; ... } 

甚至存在代码分析规则: CA1001:拥有一次性字段的类型应该是一次性的 。

类实现IDisposable接口以处置它拥有的非托管资源。 IDisposable类型的实例字段表示该字段拥有非托管资源。 声明IDisposable字段的类间接拥有非托管资源,并应实现IDisposable接口。


编辑:上述答案始终对父类拥有IDisposable成员有效。

也就是说,对于像你这样的公共属性,成员的所有权有点模糊:如果SqlConnection实例是在你的类之外创建的,那么你的类很可能实际上并不拥有该实例,但除了你之外没人知道。

关于IDisposable成员是否由其父类拥有的一个有趣的例子: StreamWriter 。 关于它有很多问题,例如看到这个线程: 有没有办法在不关闭其BaseStream的情况下关闭StreamWriter?

现在甚至有一个leaveOpen参数,因此StreamWriter不会处理它的基本流。

对于两者都是 – 如果您的类负责成员字段的生命周期,那么它需要在该对象上调用Dispose ,这意味着您的类需要实现IDisposable以便可以在正确的时间处置该成员。

但是,请注意,您可能不希望为此类成员使用公共可设置属性,因为任何人都可以直接清除,处置,取消设置,重置该字段。 您的类需要保持对该字段的控制,这意味着它只能从类本身内部设置 – 理想情况下使用private readonly字段或只读属性。