设计难题:谁应该处理一次性参数



如果我的类在其构造函数中使用可丢弃资源(如果重要的话是DbConnection),我应该在类中实现IDisposable并处理DbConnection对象,还是让用户处理DbConnection的处理?

目前,我在类中实现了IDisposable,但现在我看到了一些可能的负面影响:clutters类设计,如果使用不正确,会对DbConnection进行双重处理。但也有积极的一面:更简单的使用是主要的一面(尤其是如果你使用了多个一次性参数)。

在"狂野"中,我看到了这两种方法,所以我无法决定。。

更新:感谢大家的回答,事实上,这表明有时这确实不是一个简单的选择。而且也很难选出正确的答案。然而,我决定在未来坚持最简单的一个。所以最后的选择是:不要实现IDisposable。

它应该由创建它的人处理,与创建它的范围相同。你创建了一个对象,你负责处理它。就这么简单。

在构造函数中使用一次性资源是非最优的,可能会导致奇怪。相反,您应该将DbConnectionFactory注入到构造函数中,该构造函数能够根据需要创建连接,以便您可以使用它们并在方法内部处理它们。

如果出于某种原因,这种模式对您的场景来说是不合逻辑的。下一个最好的选择是仍然将可丢弃资源的使用从构造函数中移出,并让方法返回一个可丢弃的、符合您目的的新类型。

这类似于服务类型类返回需要从方法中释放的数据读取器。(理论上它可能是一个真正的数据读取器)

  1. 不执行IDisposable;调用代码负责处理传入的对象,并确保其寿命至少与新对象一样长

或者:

  1. 实施IDisposable;调用代码将放弃传入对象的所有权,并应将其视为已处置对象

清楚地记录了我所做的选择。IMHO说,试图在多个地方拥有一次性物品很可能有一天会出错。

选项1适用于您打算将一次性对象传递到几个新对象中的场景,这些对象将共享对它的访问权限(数据库连接听起来可能是这样的)。选项2适用于您所做的更像是将一次性对象包装在另一个具有更多(或更抽象)功能的对象中的情况,尤其是如果您正在返回它,因此不控制它的寿命。

在某些情况下,对象将使用使用寿命超过使用它的新对象使用寿命的一次性资源。在其他情况下,人们会期望将对象交给对其中任何一次性项目一无所知的实体。某些类型的对象可能会在这两种情况下都使用。

考虑一个假设的IDisposable SoundPlayer类型,它将播放IDisposableSoundSource对象,然后在播放完后自行处理。很容易想象这样的情况:人们希望能够加载一次SoundSource,播放多次,然后手动处理它。也很容易想象这样的情况:人们想加载一个SoundSource对象,然后"开火并忘记"播放器。SoundSource的创建者在播放器完成之前无法处理它,但之后将不再使用它,因此最方便的操作是由SoundPlayer处理它。

我建议,如果这两种情况至少都是合理的,那么您应该提供一个转移IDisposable所有权的工厂方法和一个不转移的工厂方法,或者您应该有一个带有参数的工厂方法来指示是否应该转移所有权。请注意,将IDisposables传递给本应使用并处置它们的类的构造函数是危险的,因为Microsoft不允许在从字段初始值设定项调用的构造函数周围使用try/catch块,而且很难确保在构造函数抛出时处置这些东西。让工厂方法调用构造函数会让错误捕获变得容易得多(尽管这仍然是一件痛苦的事情——尤其是在C#中)。

编辑--附录另一种有时有用的情况方法是让对象发布Disposed事件,或者在不再需要传入对象时在其构造函数中接受委托来运行。我更喜欢显式委托而不是事件,因为使用事件意味着事件订阅者(创建将临时拥有可支配资源的对象的人)有义务取消订阅,这增加了额外的复杂性,尤其是在对象可能被移交给另一个对象的情况下。由于到目前为止,当对象的接收者不再需要调用程序时,调用程序最想做的事情就是简单地删除对象,因此最简单的情况是简单地为对象接收者提供一个自己处理处置的选项。

最新更新