C#IDisposable问题

Yip*_*Yay 8 c# interface disposable

我有以下代码示例:

public interface IRepository {
   // Whatever
}

public class SampleRepository : IRepository {
   // Implements 'Whatever'
}

public class NHibernateRepository : IRepository, IDisposable {

   // ...

   public void Dispose() { ... }
}
Run Code Online (Sandbox Code Playgroud)

现在 - 真的很糟糕吗?我不确定,但这似乎与不标记虚拟基类的析构函数C++相同.

我不想让IRepository接口实现IDisposable,因为这会带来不必要的复杂性和一堆必须实现的类IDisposable.


该案件应如何处理?

我确信这可能发生在任何类型层次结构中 - 当派生类型之一必须管理可支配资源时.

那么我应该怎么做 - 将其拉到IDisposable第一个界面或保留它并希望用户区分一次性和非一次性存储库?

谢谢.

Jon*_*eet 15

是的,我会说这很糟糕 - 因为你不能以同样的方式使用所有存储库.

我个人会让存储库接口扩展IDisposable- 毕竟,使用no-op实现它很容易.

这是完全一样的选择,是由制作Stream,TextReaderTextWriter在主框架.StringWriter(例如)不需要处理任何东西......但TextWriter仍然是一次性的.

所有这一切都是因为IDisposable在某种程度上是一个奇怪的界面:它没有传达给呼叫者提供的东西......它传达了呼叫者所需要的东西(或者至少,强烈鼓励可能的问题,如果你不沿着这个走).


poi*_*r12 9

您可能遇到的唯一问题是使用某种类型的工厂,控制反转或依赖注入模式/框架.如果您想将对象用作接口,则永远无法执行此操作:

IRepository repo = Factory.GetRepository();
repo.Dispose();
Run Code Online (Sandbox Code Playgroud)

您可能想要引入一个实现IDisposable的INHibernateRepository.因为IDisposable通常是如此低级别的操作,所以使接口实现此接口并不是一个大问题.


sup*_*cat 3

您所描述的内容符合一个重要的附加条件:已将“IDisposable”添加到其基础的类型的对象绝不能传递给使用者,因为使用者可能最终会在未知的时间内保留或保留该对象。

基本上,IDisposable 对象的所有者必须(*) 要么负责处理对象本身,要么将对象移交给可以接受并履行责任的新所有者。最初,IDisposable 对象通常由其创建者“拥有”,但交接很常见。可以将对 IDispoable 对象的引用赋予另一个对象,而无需转移所有权;在这种情况下,所有者仍然有责任在不再需要该对象时处置该对象。为此,所有者必须知道不再需要该对象。最常见的模式是:

  1. 该对象作为参数传递给方法;方法返回后,托管该方法的对象将不会使用该对象。
  2. 该对象作为参数传递给一个方法,该方法将其存储在某个对象的字段中,但稍后可以以某种方式请求该对象销毁该引用。
  3. 可处置对象作为参数传递给由可处置对象的所有者持有所有引用的对象托管的方法;除非有请求,否则托管对象不会使用一次性对象,并且一次性对象的所有者将知道它是否永远不会再发出此类请求。

如果其中一种模式适用,那么您可能处于良好状态。如果没有,你可能会遇到麻烦。