Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/277.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#可识别的问题_C#_Interface_Disposable - Fatal编程技术网

C#可识别的问题

C#可识别的问题,c#,interface,disposable,C#,Interface,Disposable,我有以下代码示例: public interface IRepository { // Whatever } public class SampleRepository : IRepository { // Implements 'Whatever' } public class NHibernateRepository : IRepository, IDisposable { // ... public void Dispose() { ... } } 现在-

我有以下代码示例:

public interface IRepository {
   // Whatever
}

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

public class NHibernateRepository : IRepository, IDisposable {

   // ...

   public void Dispose() { ... }
}
现在-这真的很糟糕吗?我不确定,但这似乎与不在
C++
中标记基类的析构函数非常相似

我不想让
IRepository
接口实现
IDisposable
,因为这会带来不必要的复杂性和大量的类,这些类也必须实现
IDisposable


该如何处理该案件?

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

那么我应该怎么做呢?将
IDisposable
拉到第一个界面,或者让它保持原样,希望用户能够区分一次性和非一次性存储库


谢谢。

这对我来说似乎很好。有什么问题吗?

不,不要“向上拉IDisposable”。保持接口原子化、简单和独立


除非你能辩称可识别性是IRepository的一个基本特征(SamplerRepository表明并非如此),否则两者之间不应该有任何区别

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

IRepository repo = Factory.GetRepository();
repo.Dispose();

您可能希望引入一个实现IDisposable的INHibernateRepository。因为IDisposable通常是一个低级操作,所以让您的接口实现这个接口并没有什么大问题。

是的,我认为这很糟糕——因为您不能以相同的方式使用所有存储库

我个人会让存储库接口扩展
IDisposable
——毕竟,在没有操作的情况下实现它是很容易的

这与主框架中的
Stream
TextReader
TextWriter
所做的选择完全相同<代码>StringWriter(例如)不需要处理任何东西。。。但是
TextWriter
仍然是一次性的


这一切之所以发生,是因为
IDisposable
在某些方面是一个奇怪的接口:它不传递提供给调用者的东西。。。它传达了来电者所需要的信息(或者,如果你不同意,至少会强烈鼓励你提出可能的问题)。

首先,回答你的问题。处置模式不同于C++析构函数。
Dispose
方法旨在处置类所包含的资源,而不是处置类本身

< >将C++析构函数标记为<代码>虚拟< /> >的原因不存在于.NET中,因为引用类型的每个实例都有一个包含运行时类型信息的同步块。使用此方法,垃圾收集器可以适当地回收正确的内存量

至于使用
IDisposable
扩展
IRepository
,这将是一个在绝大多数情况下都可以接受的快速解决方案。我能看到的唯一反对意见是,扩展接口将需要所有派生类来实现接口。从表面上看,用NOPs实现一个接口似乎很容易(可能多次),但您不应该这样做。但是,我可以提供另一种选择

取而代之,考虑使用一个实现配置模式的抽象基类。这将遵循dispose模式的“标准”实现的结构

public abstract class Repository : IDisposable  
{ 
    public void Dispose() { Dispose(true); }
    protected virtual Dispose(bool disposing) {  } 
}

public class NHibernateRepository : Repository { /* Impl here, add disposal. */ }

public class TestRepository : Repository { /* Impl with no resources */ }

请看一看Microsoft编写的,以查看更详细的示例。

您所描述的内容与一个重要的但书是一致的:添加了“IDisposable”到其基的类型的对象决不能传递给使用者,而该使用者可能最终持有或保留该对象一段未知的时间

基本上,IDisposable对象的所有者必须(*)处理对象本身,或者将对象交给能够接受并履行责任的新所有者。最初,IDisposable对象通常由其创建者“拥有”,但移交是常见的。对IDisable对象的引用可以在不转移所有权的情况下提供给另一个对象;在该场景中,当不再需要对象时,所有者仍负责处理该对象。为了实现这一点,所有者必须知道不再需要该对象。最常见的模式是:

  • 对象作为参数传递给方法;方法返回后,承载该方法的对象将不使用该对象。
  • 该对象作为参数传递给一个方法,该方法将其存储在某个对象的字段中,但该对象稍后可能会被请求销毁引用。
  • 一次性对象作为参数传递给一个方法,该方法由一个对象托管,该对象的所有者持有所有引用;托管对象不会使用一次性对象,除非请求使用,并且一次性对象的所有者将知道它是否永远不会发出任何此类请求。
    如果这些模式中有一种适用,你可能会处于良好状态。如果没有,您可能会遇到麻烦。

    +1确切地说,如果需要,您还可以添加
    新的public void Dispose()
    。+1,
    因为您不能以相同的方式使用所有存储库和良好的示例。然而,Stream和TextWriter是不会强制继承者实现处置逻辑的类。我认为抽象基类在这里更合适。@Matt:有一个抽象基类可能更合适,是的-可能除了接口之外。当使用者“不确定”时,围绕这些IDisposable实例的创建来实现工厂,这算是一个好的解决方案吗如何/何时处置,并让工厂跟踪实例,然后在需要时处置它们?50000美元的问题是是否属于cr