Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.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# 如何处理IDisposable?_C#_.net_Idisposable - Fatal编程技术网

C# 如何处理IDisposable?

C# 如何处理IDisposable?,c#,.net,idisposable,C#,.net,Idisposable,假设我有这三门课 abstract class MyBase { //some base code here } class Foo : MyBase, IDisposable { //got at least a field I should dispose } class Bar : MyBase, IDisposable { //got at least a field I should dispose } 我有几节这样的课。我有一个拥有列表的类。我如何正确地

假设我有这三门课

abstract class MyBase
{
    //some base code here
}

class Foo : MyBase, IDisposable
{
    //got at least a field I should dispose
}

class Bar : MyBase, IDisposable
{
    //got at least a field I should dispose
}
我有几节这样的课。我有一个拥有
列表的类。我如何正确地处理所有这些类,而不必测试/强制转换以获得正确的类型,然后进行
处理

您可以使用:

foreach (var disposable in list.OfType<IDisposable>())
{
    disposable.Dispose(); 
}
foreach(类型()列表中的变量)
{
一次性的,一次性的;
}

我想说,一般来说,拥有这种类层次结构是个坏主意;这意味着客户机不能以同样的方式使用“MyBase的任何实例”,因为对于特定类型还有额外的合同。使
Base
实现
IDisposable
会更简洁,即使一些特定类型实际上并不需要它。

如果可处置性是基类合同的一部分,为什么不明确说明它

abstract class MyBase : IDisposable
{
    //some base code here

    //an abstract "implementation" of the interface
    public abstract void Dispose();
}
通过这种方式,您可以确保其所有子代实际上都是一次性的。您还可以创建集合类而不是常规列表,如下所示:

class MyBaseCollection : IEnumerable<MyBase>
{
    private List<MyBase> innerCollection;
    ....
    public void DisposeItems()
    {
       // call Dispose on each item here
    }
}
这样子代就别无选择,只能实现这些方法,否则代码将无法编译

  • 如果大多数类不需要处理,但其中一些仍然需要处理,我将在基类中声明虚拟方法:

    public virtual void Dispose(){
      Dispose(true);
      GC.SuppressFinalize(this);
    }
    
    public virtual void Dispose(bool disposing){}
    
    这个默认实现对于大多数子体来说已经足够好了,那些确实需要处理的子体可以随意覆盖它

  • 另外,由于
    Dispose()
    方法的代码几乎总是相同的,因此可以实现其中一个,而将另一个作为虚拟的,甚至是抽象的

    //should not be overridden
    public virtual void Dispose(){
      Dispose(true);
      GC.SuppressFinalize(this);
    }
    
    //must be overriden
    public abstract void Dispose(bool disposing);
    

  • 今后,请更仔细地使用您的示例-遵循.NET命名约定(
    foo
    bar
    =>
    foo
    bar
    ),使用正确的接口名称(
    iDisposable
    =>
    iDisposable
    ),不要尝试使用关键字(
    base
    )作为标识符。这些错误不会阻止我们帮助你,但它们会不必要地分散你的注意力。@JonSkeet编辑了这个名字。TY我应该在MyBase上实现
    IDisposable
    ,即使它没有任何东西要处理吗?@im_a_noob:如果所有(甚至大多数)派生类都需要
    IDisposable
    ,那么它是一个有效的选项。与
    System.IO.Stream
    比较,请注意
    MemoryStream
    没有要处理的内容。不,只需添加
    public abstract void Dispose()因此满足编译器的要求。查找std模式。您需要一个
    受保护的虚拟void Dispose(bool disposing){}
    //should not be overridden
    public virtual void Dispose(){
      Dispose(true);
      GC.SuppressFinalize(this);
    }
    
    //must be overriden
    public abstract void Dispose(bool disposing);