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

Lea*_*ner 8 .net c# garbage-collection 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();
            }
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

注意:我知道在实施时需要遵循一种模式,IDisposable但我的问题非常具体到上述情况.

ken*_*n2k 6

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

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


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

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

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

现在甚至有一个leaveOpen参数,所以StreamWriter不会处理它的基本流.

  • 是的,*拥有*IDisposable的类型应该保持(即*处置*它们).但是,问题中的类似乎没有*`SqlConnection`:看到公共"set" - 所以你可以将*任意*`SqlConnection`分配给`Helper`实例.`Helper`*使用*SqlConnection,这就是为什么*不应该处理*它. (2认同)

Dmi*_*nko 5

It depends. If your class creates and owns the IDisposable it must dispose it (so, both answers are "yes"). If your class just uses IDisposable it must not dispose it (so the first answer is, usually, "no" and the second answer is "no").

In your case, it seems that Helper class

  public class Helper
  {
      // Note, that you can assign any arbitrary Connection via this property
      public SqlConnection SqlConnection { get; set; }
      ....
  }
Run Code Online (Sandbox Code Playgroud)

just uses SqlConnection (because it provides "set") in the way like

// 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; 
  };

  ...
}
Run Code Online (Sandbox Code Playgroud)

so it must not dispose the connection. On the contrary, a class like that

public class Helper: IDisposable {
  private SqlConnection m_SqlConnection;

  // Note the absence of public "set"
  public SqlConnection SqlConnection {
    get {
      return m_SqlConnection; 
    } 
  }
  ...
}  
Run Code Online (Sandbox Code Playgroud)

owns its SqlConnection so it's responsible for disposing it:

using (Helper helper = new Helper(...)) {
  ...
  // it's helper that owns SqlConnection
  SqlConnection con = helper.SqlConnection;
  ...
} 
Run Code Online (Sandbox Code Playgroud)