.net 设计困境:谁来处理一次性参数?

.net 设计困境:谁来处理一次性参数?,.net,class-design,idisposable,.net,Class Design,Idisposable,如果我的类在其构造函数中使用了一次性资源(DbConnection,如果有必要),我应该在类中实现IDisposable,并处理DbConnection对象,还是让用户处理DbConnection的处理 目前我在我的类中实现了IDisposable,但现在我看到了一些可能的负面影响:混乱的类设计,如果使用不正确,会重复处理DbConnection。但也有积极的一面:更简单的使用是主要的(特别是如果使用多个一次性参数) 在“荒野”中,我看到了两种方法,因此我无法决定 更新: 谢谢大家的回答,事实上

如果我的类在其构造函数中使用了一次性资源(
DbConnection
,如果有必要),我应该在类中实现
IDisposable
,并处理
DbConnection
对象,还是让用户处理
DbConnection
的处理

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

在“荒野”中,我看到了两种方法,因此我无法决定

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

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

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


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

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

我会:

  • 未实现IDisposable
    ;调用代码负责处理传入的对象,并确保它至少与新对象一样长
  • 或:

  • 实现IDisposable
    ;调用代码放弃传入对象的所有权,并应将其视为已处置
  • 清楚地记录我所做的选择。IMHO说,试图在多个地方拥有一次性物品很可能有一天会出错


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

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

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

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

    编辑——附录
    另一种有时有用的方法是让对象发布已处理事件或在其构造函数中接受委托,以便在不再需要传入的对象时运行。我更喜欢事件的显式委托,因为使用事件将意味着事件订阅者(创建将临时持有可支配资源的对象的人)有义务取消订阅,这会增加额外的复杂性,特别是当对象可能被传递给另一个对象时。由于到目前为止,当对象的接收者不再需要对象时,调用方希望做的最常见的事情是简单地删除对象,最简单的情况是让对象接收者自己处理处置。

    +1对于工厂,这可能是最干净、最明确的方法。如果您自己没有实现IDisposable,那么传递给您的dbConnection的所有者必须知道您何时完成了它。根据你的具体情况,这可能是方便的,也可能是尴尬的。我个人喜欢传递一个标志的方法,该标志表示接收IDisposable的对象是否应该拥有所有权;编码并不困难,含义也很清楚。你不喜欢那种方法吗?