经过很多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 回答
管理对象将在未来的某些非确定性点通过垃圾收集自动处理 . 但是,当处理可能包含非托管资源的对象(不受CLR /垃圾回收控制)时,应实现IDisposable以提供将这些资源返回给操作系统的一致且确定的方法 .
当在using()的上下文中使用对象时,该接口仅提供任何实际好处阻止 . 这样的一个块告诉CLR在它到达块的右括号时调用Dispose方法 . 所以无论在这个块内发生什么(没有一些灾难性的系统故障),都可以保证调用Dispose方法并释放你的非托管资源 .
例如,在您提供的代码中,如果抛出异常,则可能永远不会调用您的Release()方法,可能会使连接保持打开状态 . 但是,当使用带有using块的一次性对象时,抛出异常时,CLR会在抛出异常之前跳入并调用Dispose方法 .
你是对的,使用你的Release方法你会得到完全相同的效果,只要你总是记得调用它 .
您应该使用
Dispose
/IDisposable
这类事情的原因是一致性 . 所有.NET开发人员都会知道IDisposable模式,而一个IDisposable类表示你应该处理它,并使用Dispose方法来完成它 . 换句话说,使用IDisposable模式会立即告诉另一个开发人员,他应该释放该类所拥有的资源,他应该通过调用Dispose
方法来完成它 .实现
IDisposable
的另一个好处是using块,它适用于任何IDisposable类:使用上面的代码将导致
t
在using
块的末尾被Dispose()
编辑 . 它是try
...finally
块的语法糖,但它往往使这种代码更简洁,更容易读写 .如果你的
Release()
工作正常(它不是另一回事),那么人们就必须了解它,并与另一个类学习其他东西,等等 .永远无法以编程方式找到您的
Release()
. 在适用的情况下,可以以编程方式调用Dispose()
:if(obj是IDisposable)((IDisposable)obj) . Dispose();
虽然不常做,但一旦完成,它是至关重要的 .
如果有人可能想要在对象使用期间调用它,那么有时候像_1247362这样的方法很有用 . 一个例子是
Close()
在Stream
上 . 请注意,虽然Stream.Dispose()
仍然存在,但调用Close()
.IDisposable值得实现,主要是因为它在C#中是个性的 . 每个人都知道IDisposable做了什么,以及如何处理实现IDisposable的对象 . 当您使用IDisposable.Dispose()之外的其他内容释放资源时,您将偏离一般理解的习语 .
这意味着维护者不必知道您的特定类的来龙去脉,以防止泄漏资源 . 这可能是你在6个月内,当你忘记了你用这段代码完成的大部分工作时!您需要知道的是它实现了IDisposable,它具有通常理解的含义 .
请记住,IDisposable,主要是给开发人员的信号,“嘿,我是一个持有非托管资源引用的类 . 你可能不应该等垃圾收集器来清理我 . ”请注意,这可能是间接通过组合(实现IDisposable的类,因为它具有实现IDisposable的私有成员) . 当一个体面的C#开发人员看到一个实现IDisposable的类时,他们应该立即想到“这个对象很特殊,需要在我完成它时进行清理” . 没有什么可以阻止你编写Release()方法;它只是意味着你更有可能不小心泄漏资源,因为你没有使用惯用模式 .