这是我在.NET中从未完全掌握的.dispose()方法的正确应用。
说我有类似
的东西Public Class someClass()
sub someMethod
' do some stuff tying up resources
end sub
End Class
public class mainApp
dim _class as new SomeClass
_class.someMethod()
End Class
在所有情况下,实施dispose方法都是一种好习惯,如果是这样,应该去哪里?
如果不是每个班级都应该有处理方法(我的直觉不应该说)应该是什么类?我一直认为任何可能占用资源的东西(即连接,datareader等)都应该有一个.dispose(),它会取消分配这些资源。
另外,如何强制调用.dispose()方法?
答案 0 :(得分:6)
完全涵盖所有内容是一个相当长的答案,所以如果我链接到a blog post which should hopefully answer everything,没有人会介意。
答案 1 :(得分:5)
我强烈建议在MSDN上阅读Cleaning Up Unmanaged Resources,它有文章介绍何时使用Dispose以及如何正确实现IDisposable。您的直觉本质上是正确的,因为您很少需要实现IDisposable,除非您的类使用非托管资源或者是实现IDisposable的对象的容器。
至于强制调用Dispose,当你正确实现IDisposable接口时,你会附加一个终结器,它调用Dispose来捕获那些遗忘的落后者和异常类。
相关文章:
<强> Implementing a Dispose Method 强>
描述用于释放非托管资源的Dispose方法的实现。
<强> Using Objects That Encapsulate Resources 强>
描述确保调用Dispose方法的方法,例如C#using语句(在Visual Basic中使用)。
(编辑:添加了其他信息)
在您的示例中,您有 SomeClass.SomeMethod ,它可以完成一些工作,大概是使用资源。如果此资源不是类成员,则可以更好地将其包装在using-statement中,并忘记IDisposable的恶魔细节。
Public Class someClass()
sub someMethod
Using someResource As New ResourceType( arguments )
' no worries about IDisposable for someResource, as it is automatic
End Using
end sub
End Class
答案 2 :(得分:1)
关于IDisposable有很多错误的信息。它是一个PATTERN,有助于完成以前通过C ++中的析构函数完成的工作。问题是在.NET中,对象的破坏不是确定性的(当对象超出范围时它不会自动发生,而是在垃圾收集时发生,而垃圾收集是在一个单独的低优先级线程上)。 / p>
除非您拥有需要以某种方式发布的资源,否则不需要实现Dispose。例如,如果您的任何私有数据成员实现Dispose,您可能也应该实现Dispose并在Dispose中的那些私有成员上调用Dispose。同样,您应该在Dispose中释放任何PInvoke句柄。
此外,在收集垃圾时,不会自动为您调用Dispose方法。这是最大的错误信息。您必须从析构函数(C#)或Finalize(VB.NET)调用Dispose。这是实现Dispose的一个很好的模式:
public class Foo : IDisposable
{
public Foo()
{
// Allocate some resource here
}
~Foo()
{
Dispose( false );
}
public void Dispose()
{
Dispose( true );
}
private void Dispose( bool disposing )
{
// De-allocate resource here
if ( disposing )
GC.SuppressFinalize( this );
}
}
你调用GC.SupressFinalize的原因是如果你的对象有一个终结器,你的对象实际上会升级到下一代GC,因为它必须在GC第一次运行时调用Finalize,而不能释放您的对象,直到完成结束,因此在GC第二次运行之前,内存实际上不会被释放。如果您手动调用Dispose,则可以跳过终结器,允许在GC的第一次传递期间释放您的对象。
要从Dispose中获得最大收益,请使用using keword:
using ( Foo f = new Foo() )
{
// Do something with Foo
}
这与你写下来的完全相同:
Foo f;
try
{
f = new Foo();
// Do something with Foo
}
finally
{
f.Dispose();
}
有些人喜欢在他们的类中设置一个名为_disposed的布尔值,然后在每个方法调用期间检查bool,如果在调用Dispose后尝试调用对象上的方法,则抛出异常。对于内部项目类,我通常认为这有点过分,但如果您要创建供第三方使用的库,则可能是一件好事。
答案 3 :(得分:0)
Dispose()
方法用于尽早清理所有资源。尽管垃圾收集器会为您回收任何未使用的内存,但您可以自行处理网络/数据库连接和文件句柄等操作。通常情况下,您希望这些东西在不再需要时立即释放,因此您可以实现一次性模式并利用Using
语句在后台的try / finally块中调用它。
答案 4 :(得分:0)
一般情况下,只要您的课程打算打开某些内容,就应该实施IDisposable。无论是文件的句柄,与数据库的连接,还是某些会占用大量内存的资源,或者会使应用程序处于不稳定状态的资源,实现IDisposable以指定代码都是一个好主意。关闭这些资源。
您实际上无法强制其他开发人员调用您的dispose方法,但自动实现IDisposable意味着我们可以使用Using语句;一旦你养成习惯,就很难打破:)
答案 5 :(得分:0)
如果类是:
,您应该在类中实现IDisposable