我应该使用包含TransactionScope的IDisposable类的finalize方法吗?

时间:2012-08-15 08:12:13

标签: c# linq-to-sql datacontext idisposable transactionscope

我写了一个类,它将TransactionScope与Linq配对为Sql DataContext

它实现了与TransactionScopeDispose()Complete()相同的方法,并公开了DataContext。

它的目的是确保DataContexts不被重复使用,它们与单个事务配对并随之一起处理。

我应该在课程中包含Finalize方法吗?如果尚未调用Dispose,则调用它?或者仅适用于引用非托管资源的IDisposable?

2 个答案:

答案 0 :(得分:3)

Finalizer仅用于清理非托管资源。在终结器中调用依赖对象的处理是没有用的,因为如果这些对象管理关键资源,他们就会有自己的终结器。

在.NET 2.0及更高版本中,实现终结器的理由更少,没有.NET包含SafeHandle类。

然而,我有时发现仍然实现终结器的一个原因是要弄清楚开发人员是否忘记调用Dispose。我让这个类只在调试版本中实现终结器,然后让它写入Debug窗口。

答案 1 :(得分:1)

这个问题没有简单的答案 - 这是值得商榷的。

什么?

争论的焦点是,是否使用具有完整 Disposable 模式的finaliser。您的代码使用事务和数据库上下文 - 那些人(通常)使用非托管资源(如内核事务对象和TCP / IP连接)

为什么?

如果您使用任何应清理的非托管资源,则应实施IDisposable。然后,客户端代码可以将对类的调用包装到推荐的using(IDisposable myClass = new MyClass(){...}构造中。问题是如果开发人员不能显式或隐式地调用IDisposable.Dispose(),那么资源就不会自动释放。即使GC已收集对象myClass。这是因为GC在收集过程中从不调用Dispose,它是终结队列的责任。

因此,您可以定义一个最终由GC finilisation线程调用的finiliser,它独立于垃圾收集。

评论

有些人认为你应该确保将所有一次性代码放入using (){}并忘记了终结。毕竟你必须尽快释放这些资源,并且对于许多开发人员而言,整个完成过程有点模糊。

相比之下,我更喜欢明确地实现finilisator,因为我不知道谁将使用我的代码。因此,如果某人忘记在需要该类的类上调用Dispose,则该资源最终将被释放。

结论

就个人而言,我建议在任何实现IDisposable的类中实现finilisator。