什么是IDisposable替代用途?

时间:2011-05-24 08:37:08

标签: c# idisposable msdn

System.IDisposable接口的msdn文档说明了

  

主要使用此接口是为了释放非托管资源。

我想知道什么是替代用途。

例如,我们还需要IDisposable接口用于其他已分配的资源,例如事件订阅等。

我们使用接口作为标记,以允许类实例知道何时不再使用客户端。只要不再需要实现代码的类的逻辑实例,客户端和基础结构代码就会显式调用IDisposable.Dispose()。 与接口包装的非托管资源无关。

当我们为这种行为选择IDisposable接口时,我们将其视为接口的替代(未记录)使用。

您找到的IDisposable的替代用途是什么? 他们合法吗? MSDN文档是错误的吗?

6 个答案:

答案 0 :(得分:2)

IDisposable通常与用于激活和停用某个明确范围内的内容一起使用,即使它不是非托管资源。使用时将声音描述为引用计数,并且不建议使用。

答案 1 :(得分:2)

我认为您阅读文档是错误的。假设任何与非托管资源无关的IDisposable用法都没有记录,这有点像说任何不计算事物的System.Int32用法都没有记录。它是一个接口,没有实现,甚至没有功能可以开始区分记录的内容和未记录的内容。

IDisposable的目的只是为开发人员提供一种确定性地控制其对象生命周期的机制。事实恰恰相反,这主要是处理非托管资源的要求。

IDisposable的一个更奇特的用法是using阻止句法糖。正如其他人所提到的那样,using块给出了操作范围,我认为这些块非常优雅。

示例1 - 时序块

StackOverflow使用mini profiler使用using块来识别嵌套的执行区域:

using (profiler.Step("Doing complex stuff"))
{
    using (profiler.Step("Step A"))
    { // something more interesting here
        Thread.Sleep(100);
    }
    using (profiler.Step("Step B"))
    { // and here
        Thread.Sleep(250);
    }
}

不使用using的替代方案非常可怕,我甚至不想在这里嘲笑它。

示例2 - 一次性行动

在.NET Domain Driven Design圈子中,一次性动作模式的轮次有不同的变化。 Ayende有one,Udi Dahan在他的Domain Events implementation中也是如此,Jimmmy Bogard有一个slightly different take on this,仍然在Domain Events的背景下。模式的关键在于您希望在某些上下文中执行某些操作,然后让上下文恢复到完成之后的状态。

Ayende提供了一个简单的例子:

class UsuallyReadOnly { 
  //.. implementation
  public IDisposable AllowModification
  {
    get 
    {
        _allowModification = true;
        return new DisposableAction(()=>{ _allowModification = false; } );
     }
  }
}

UsuallyReadOnly的用法:

UsuallyReadOnly foo = new UsuallyReadOnly();
using(foo.AllowModification)
{
  foo.Name = "Bar";
}

答案 2 :(得分:1)

对于“资源”,替换“责任”。当一个对象被认为拥有一个非托管资源时,真正意味着有一些任务需要在某个时候完成,并且该对象是唯一具有执行它所需的信息和动力的东西。 “Dispose”的目的不是为了摆脱任何有形的实体,而是让一个对象“把它的事务整理好”。在他死前没有对自己做任何事情之前,有人正在将他的事务整理好,而是确保他必须对自己以外的人和事做的事情完成。与IDisposable.Dispose一样。

答案 3 :(得分:0)

请记住还有使用模式,其行为有点像 RAII

using ( DisposableObject obj = new DisposableObject( ) )
{

    .....
}

在退出使用块时调用Dispose

答案 4 :(得分:0)

IDisposable接口更常用的一个用途是事务范围。您可以使用它在事务中包装一些SQL逻辑,并显式调用Complete()来结束事务:

using (var scope = new TransactionScope())
{
    using (var connection = new SqlConnection(connectString))
    {
        // perform sql logic
        ...

        scope.Complete(); 
    }
}

您也可以对需要临时功能的任何事情使用类似的模式,例如创建和删除临时文件:

public class TempFileProvider : IDisposable
{
    public Filename { get; private set; }

    public TempFileProvider()
    {
        Filename = Path.GetTempFileName();
    }

    public void Dispose()
    {   
        File.Delete(Filename);
    }
}

所以你可以使用它:

using (var tempFileProvider = new TempFileProvider())
{
    DoSomethingWithFile(tempFileProvider.Filename);
} // deletes temp file

答案 5 :(得分:0)

查看以下问题Need an alternative to my IDisposable Hack

我给出了一个很好的例子,说明了我使用IDisposable的原因。 :)

当然,这不是理想的解决方案,但它对我帮助很大。