如果我的类定义了字段类型实现dispose模式的字段,我是否应该始终实现dispose模式? C#

时间:2016-09-01 14:53:44

标签: c# .net idisposable

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

  

重要如果某个类定义了字段类型的字段   实现dispose模式,类本身也应该实现   处置模式。 Dispose方法应该处理该对象   该领域提到的。这允许使用该类的人来打电话   处理它,然后释放对象使用的资源   本身。

在以下示例中是否会这样?

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

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

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

2 个答案:

答案 0 :(得分:2)

  

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

答案 1 :(得分:1)

几乎从来没有一个场景总是"总是"是合适的。在很多场景中,这既可以是真实的,也可以是不正确的。这是以下示例

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