如果我的 class 定义了一个字段,该字段的类型在其中实现了处置模式,我是否应该始终实施处置模式? C#

Should I always implement the dispose pattern if my class defines a field in which the field’s type implements the dispose pattern? c#

我最近在 Jeffery Richter 的 "CLR via C#" 中读到了这篇文章;

Important If a class defines a field in which the field’s type implements the dispose pattern, the class itself should also implement the dispose pattern. The Dispose method should dispose of the object referred to by the field. This allows someone using the class to call Dispose on it, which in turn releases the resources used by the object itself.

在下面的例子中会是这样吗?

public class SomeClass
{
    private readonly StreamReader _reader; //a disposable class

    public SomeClass(StreamReader reader)
    {
        _reader = reader;
    }
}

尽管 StreamReader 是一次性的 class 它的实例已通过构造函数传入,因此可能会在其他地方引用它,因此在 SomeClass 上实现 IDisposable 以便可以处置 _reader 似乎是个坏主意. Jeffery Richter 试图提出的观点是否仅适用于 classes,其中一次性 classes 的实例是在 class 中实例化的?

Although StreamReader is a disposable class its instance has been passed in via the constructor, it will therefore probably be referenced somewhere else and so implementing IDisposable on SomeClass

这真的取决于。通常,当您持有一次性资源时,实施 IDisposable 是一个很好的经验法则。但是,如果您知道其他人将持有对所述资源的引用,则可以在 class 构造函数中创建一个重载,它明确地 询问 调用者如果他想让你处置:

public class SomeClass : IDisposable
{
    private readonly StreamReader _reader; //a disposable class
    private bool shouldDispose;

    public SomeClass(StreamReader reader) : this(reader, true)
    {
    }

    public SomeClass(StreamReader reader, bool shouldDispose)
    {
        _reader = reader;
        this.shouldDispose = shouldDispose;
    }

    public void Dispose()
    {
        if (shouldDispose)
        {
            Dispose(true);
        }
    }

    protected void Dispose(bool isDisposing)
    {
        if (isDisposing)
        {
            _reader.Dispose();
        }
    }
}

几乎没有任何情况下 "always" 是合适的。在很多情况下,这可能是正确的,也可能不是正确的。这是下面的例子

public class DbSomething : IDisposable
{
    private SqlConnection _connection;

    public DbSomething (SqlConnection connection){
       _connection = connection;
    }

~DbSomething() {
     Dispose(true);
}
bool disposed = false;

public void Dispose()
{ 
   Dispose(true);
   GC.SuppressFinalize(this);           
}


protected virtual void Dispose(bool disposing)
{
  if (disposed)
     return; 

  if (disposing) 
  {
     _connection.Dispose();
  }
  disposed = true;
 }
}

现在,如果此 class 实现 IDisposable 并释放连接,如果此连接将在其他地方使用,会发生什么情况? class 正在修改不属于它的对象的状态。

因此,

public class DbSomething : IDisposable
{
    private SqlConnection _connection;

    public DbSomething (){
       _connection = new SqlConnection();
    }

    //same dispose
}

此 class 控制了 SqlConnection 对象。它创建了它,它应该处理掉它。那么,如果您将 SqlConnection public 设置为供其他内容使用会怎样?

public class DbSomething
{
    public SqlConnection Connection;

    public DbSomething (){
       Connection = new SqlConnection();
    }

   //same dispose  
}

现在我仍然默认,那个对象创建了它,那个对象应该摆脱它,但根据代码,这可能是不可能的。它可能只是一个工厂来创建一个最终需要处理的长寿命对象,之后就不再需要创建对象了。在这种情况下,让创建对象处理它成为一个问题,因此即使前两个场景看起来是个好主意,但偏离它们是合适的选择。

该方法也可以是这样的,它甚至不保存要处理的对象的实例:

public class DbSomething
{
   public SqlConnection CreateSqlConnection () => return new SqlConnection();
}