首页 文章

编写我们自己的Dispose方法而不是使用Idisposable

提问于
浏览
8

经过很多Idisposable的文章后,我对它的用法感到困惑 . 所有文章都解释了它是什么以及如何实现 . 我想知道如果我们不知道我们将会错过什么_127342_ s举一个例子通常使用dispose显示为处理 database connection.

代码就像

Public class Test:Idisposable
{
  public Test()
  {
     DatabaseConnection databaseConnection = new DatabaseConnection();
  }

  public void Dispose()
  {
     if (this.databaseConnection != null)
     {
      this.databaseConnection.Dispose();
      this.databaseConnection = null;
     }
  }
}

尽管配置已实现但是在dispose方法中,databaseconnection的dispose属性用于释放连接(this.databaseConnection.Dispose();)

我的问题是 why do we need to implement IDisposable in this case? 我们可以直接调用this.databaseConnection.Dispose()并释放连接 . 为什么在内部实现dispose也调用对象的dispose属性 . 作为Idisposable方法的替代方案,我们可以实现一个方法 Release 来释放内存 .

Public Class Test
{

public Test()
{
  DatabaseConnection databaseConnection = new DatabaseConnection();
}
public void Release()
{
   if (this.databaseConnection != null)
   {
      this.databaseConnection.Dispose();
      this.databaseConnection = null;
   }

}
}

这两种方法有什么不同?我们真的需要Idisposable吗?我期待着一个具体的解释 .

5 回答

  • 12

    管理对象将在未来的某些非确定性点通过垃圾收集自动处理 . 但是,当处理可能包含非托管资源的对象(不受CLR /垃圾回收控制)时,应实现IDisposable以提供将这些资源返回给操作系统的一致且确定的方法 .

    当在using()的上下文中使用对象时,该接口仅提供任何实际好处阻止 . 这样的一个块告诉CLR在它到达块的右括号时调用Dispose方法 . 所以无论在这个块内发生什么(没有一些灾难性的系统故障),都可以保证调用Dispose方法并释放你的非托管资源 .

    例如,在您提供的代码中,如果抛出异常,则可能永远不会调用您的Release()方法,可能会使连接保持打开状态 . 但是,当使用带有using块的一次性对象时,抛出异常时,CLR会在抛出异常之前跳入并调用Dispose方法 .

  • 1

    你是对的,使用你的Release方法你会得到完全相同的效果,只要你总是记得调用它 .

    您应该使用 Dispose / IDisposable 这类事情的原因是一致性 . 所有.NET开发人员都会知道IDisposable模式,而一个IDisposable类表示你应该处理它,并使用Dispose方法来完成它 . 换句话说,使用IDisposable模式会立即告诉另一个开发人员,他应该释放该类所拥有的资源,他应该通过调用 Dispose 方法来完成它 .

    实现 IDisposable 的另一个好处是using块,它适用于任何IDisposable类:

    using(var t = new Test())
    {
        // use t
    }
    

    使用上面的代码将导致 tusing 块的末尾被 Dispose() 编辑 . 它是 try ... finally 块的语法糖,但它往往使这种代码更简洁,更容易读写 .

  • 1
    • 如果你的 Release() 工作正常(它不是另一回事),那么人们就必须了解它,并与另一个类学习其他东西,等等 .

    • 永远无法以编程方式找到您的 Release() . 在适用的情况下,可以以编程方式调用 Dispose()

    if(obj是IDisposable)((IDisposable)obj) . Dispose();

    虽然不常做,但一旦完成,它是至关重要的 .

    如果有人可能想要在对象使用期间调用它,那么有时候像_1247362这样的方法很有用 . 一个例子是 Close()Stream 上 . 请注意,虽然 Stream.Dispose() 仍然存在,但调用 Close() .

  • 0

    IDisposable值得实现,主要是因为它在C#中是个性的 . 每个人都知道IDisposable做了什么,以及如何处理实现IDisposable的对象 . 当您使用IDisposable.Dispose()之外的其他内容释放资源时,您将偏离一般理解的习语 .

    这意味着维护者不必知道您的特定类的来龙去脉,以防止泄漏资源 . 这可能是你在6个月内,当你忘记了你用这段代码完成的大部分工作时!您需要知道的是它实现了IDisposable,它具有通常理解的含义 .

    请记住,IDisposable,主要是给开发人员的信号,“嘿,我是一个持有非托管资源引用的类 . 你可能不应该等垃圾收集器来清理我 . ”请注意,这可能是间接通过组合(实现IDisposable的类,因为它具有实现IDisposable的私有成员) . 当一个体面的C#开发人员看到一个实现IDisposable的类时,他们应该立即想到“这个对象很特殊,需要在我完成它时进行清理” . 没有什么可以阻止你编写Release()方法;它只是意味着你更有可能不小心泄漏资源,因为你没有使用惯用模式 .

  • 1
    public class DotNetTips     
    {     
    private void DoSomeOperation()     
    {     
    using (SqlConnection con1 = new SqlConnection("First Connection String"), 
                con2 = new SqlConnection(("Second Connection String"))     
    {     
    // Rest of the code goes here     
    }     
    }
    
    private void DoSomeOtherOperation()    
    {     
    using (SqlConnection con = new SqlConnection("Connection String"))     
    using (SqlCommand cmd = new SqlCommand())     
    {     
    // Rest of the code goes here     
    }     
    }     
    }
    Using statement is useful when we have to call dispose method multiple times on different objects. Otherwise, we will have to call Dispose method on each object as:
    
    
    if (con != null) con.Dispose();     
    if (cmd != null) cmd.Dispose();
    

相关问题