C#中的IDisposable实现-是否可以对注入的IDisposable进行可选处理?

C#中的IDisposable实现-是否可以对注入的IDisposable进行可选处理?,c#,idisposable,C#,Idisposable,如果我有一个标准的抽象类,它允许注入IDisposable实例。但是,从这个类继承的一些类不应该像其他类一样处理注入的存储库。显而易见的解决方案是有一个构造函数: public abstract class WorkspaceViewModel : IDisposable { readonly bool _cascadeDisposeRepository; protected WorkspaceViewModel(IRepository repository, bool casc

如果我有一个标准的抽象类,它允许注入IDisposable实例。但是,从这个类继承的一些类不应该像其他类一样处理注入的存储库。显而易见的解决方案是有一个构造函数:

public abstract class WorkspaceViewModel : IDisposable
{
    readonly bool _cascadeDisposeRepository;
    protected WorkspaceViewModel(IRepository repository, bool cascadeDisposeRepository=true)
    {
        _repository = repository;
        _cascadeDisposeRepository = cascadeDisposeRepository;
    }
编辑:

我也有一个构造函数

    protected WorkspaceViewModel()
        :this(new RepositoryA(), true){} 
结束编辑

然后在

然而,我从未见过IDisposable以这种方式实现,我想知道这是否是一种不好的做法(如果是,为什么,还有什么更好的解决方案)

谢谢你的想法

编辑:
Mark的评论让我意识到,最好的实现可能是不使用无参数构造函数,强制从WorkspaceViewModel继承的任何类创建和处理自己的实例(并选择实现IDisposable),从WorkspaceViewModel的已实现接口中删除IDisposable时。

由于您对非托管资源没有句柄,我建议将IDisposable全部删除

由于您的类是一个存储库,我怀疑它使用的数据库连接可能间接地在非托管资源上具有句柄-因此请记住将其包装在一个使用:

using(var myConn = new Connection(connectionString))
{
}
然后你就可以让托管代码的美妙之处去担心要销毁什么和保存什么——你甚至不需要考虑它。

最后一个“使用”实现
IDisposable的对象的实体,可以直接访问它,也可以将它传递给其他实体以供已知的临时使用,应在其上调用
Dispose
。如果
Moe
从某个其他实体传递了
IDisposable
,该实体将固有地知道Moe何时处理它,那么Moe通常可以期望其他实体处理它,而不需要调用
Dispose
本身。事实上,如果Moe使用了
IDisposable
后,其他实体可能会使用它,则Moe不得调用
Dispose
本身。如果
Moe
传递了接口或基类类型的引用,则接口或基类不需要实现
IDisposable
;即使传入的实例可能是实现
IDisposable
的派生类型,这也不是Moe关心的问题。创建该实例的实体应该知道它是一种实现
IDisposable
并处理它的类型


事情变得棘手的地方是工厂方法。如果工厂方法可能返回一个实现了
IDisposable
的对象,并且该方法的调用方是唯一知道何时不再需要该对象的对象,那么该方法的返回类型本身应该实现
IDisposable
。由于非泛型
IEnumerator
接口没有遵循该模式,因此使用非泛型
IEnumerable
接口的代码需要检查
GetEnumerator()
implements
IDisposable
返回的每个对象,如果是,则对其调用
Dispose
;与无条件地调用
IDisposable
相比,如果它被
IEnumerator继承,那么调用它的方便性和速度要低得多[即使只有99.9%的
IEnumerator
实现会使用do nothing
Dispose
方法,调用已知接口支持的do nothing方法要比检查接口是否支持方法快]。请注意,让factory方法的返回类型实现或继承
IDisposable
不会给调用方增加任何责任——这只会使调用方更容易履行他们将要承担的责任。

您是否拥有非托管资源的句柄?否则,您根本不应该使用IDisposable(虽然你不会是第一个)。不,在这个抽象类中除了IRepository之外,没有其他非托管资源-我将编辑这篇文章来展示更多的代码,以及我为什么这样做
using(var myConn = new Connection(connectionString))
{
}