【问题标题】:Should I always implement the dispose pattern if my class defines a field in which the field’s type implements the dispose pattern? c# [duplicate]如果我的类定义了一个字段类型实现了 dispose 模式,我是否应该始终实现 dispose 模式? c# [重复]
【发布时间】:2025-12-20 21:50:13
【问题描述】:

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

重要如果一个类定义了一个字段,该字段的类型 实现了 dispose 模式,类本身也应该实现 处置模式。 Dispose 方法应该处理对象 领域所指。这允许使用该类的人调用 Dispose 就可以了,反过来释放对象使用的资源 自己。

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

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

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

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

【问题讨论】:

  • 您可能会考虑一个接受bool closeStream 参数的构造函数,以便调用者可以控制流是否在处理时关闭。即使在这种情况下,我仍然会实现 IDisposable 并在 Dispose() 方法中,如果实例化器希望流关闭,则关闭流。

标签: c# .net idisposable


【解决方案1】:

虽然 StreamReader 是一个一次性类,但它的实例一直是 通过构造函数传入,因此它可能是 在其他地方引用,因此在 SomeClass 上实现 IDisposable

这真的取决于。一般来说,当您持有一次性资源时,实施IDisposable 是一个很好的经验法则。但是,如果您知道其他人将持有对所述资源的引用,您可以在您的类构造函数中创建一个重载,显式询问调用者是否希望您处理:

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();
        }
    }
}

【讨论】:

  • 感谢您的回复。您说“如果您知道其他人将持有参考” - 我看不到该类可能知道这一点,因此我不应该在 Dispose 方法中处置读者,因为其他东西可能会尝试使用阅读器,发现它已经被处理掉了。
  • @mark_h 班级不会知道。但是,无论谁消费你的课程,都应该知道他是否只在那儿传递阅读器,或者他是否还持有对阅读器的引用。
  • 我同意你的观点,他们会持有对阅读器的引用,然后处理他们传递给它的类,然后再次尝试使用阅读器,这对他们来说不是火箭科学找出哪里出了问题,如果这确实是最佳实践,他们实际上应该期待它。
  • “shouldDispose”开关的想法让我放心了,我可以决定将来如何处理这种情况。谢谢
【解决方案2】:

几乎从不存在“总是”一词适合的情况。在很多情况下,这可能是真的,也可能不是真的。下面是一个例子

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

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

因此,

public class DbSomething : IDisposable
{
    private SqlConnection _connection;

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

    //same dispose
}

这个类可以控制 SqlConnection 对象。它创造了它,它应该处理它。那么,如果您将 SqlConnection 公开以供其他事物使用,会发生什么情况呢?

public class DbSomething
{
    public SqlConnection Connection;

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

   //same dispose  
}

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

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

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

【讨论】:

    最近更新 更多