小编典典

使用IDisposable和“使用”作为获取“范围行为”以确保异常安全的手段是否在滥用?

c#

我经常在C
++中使用的一种方法是让类通过构造函数和析构函数A处理另一个类的状态进入和退出条件,以确保如果该范围内的某个事物引发了异常,则当范围已退出。就首字母缩略词而言,这并不是纯粹的RAII,但这仍然是一个既定模式。B``A

在C#中,我经常想做

class FrobbleManager
{
    ...

    private void FiddleTheFrobble()
    {
        this.Frobble.Unlock();
        Foo();                  // Can throw
        this.Frobble.Fiddle();  // Can throw
        Bar();                  // Can throw
        this.Frobble.Lock();
    }
}

需要这样做

private void FiddleTheFrobble()
{
    this.Frobble.Unlock();

    try
    {            
        Foo();                  // Can throw
        this.Frobble.Fiddle();  // Can throw
        Bar();                  // Can throw
    }
    finally
    {
        this.Frobble.Lock();
    }
}

如果我想保证返回Frobble时的状态FiddleTheFrobble。该代码将更好

private void FiddleTheFrobble()
{
    using (var janitor = new FrobbleJanitor(this.Frobble))
    {            
        Foo();                  // Can throw
        this.Frobble.Fiddle();  // Can throw
        Bar();                  // Can throw
    }
}

这里FrobbleJanitor看起来 大致 一样

class FrobbleJanitor : IDisposable
{
    private Frobble frobble;

    public FrobbleJanitor(Frobble frobble)
    {
        this.frobble = frobble;
        this.frobble.Unlock();
    }

    public void Dispose()
    {
        this.frobble.Lock();
    }
}

这就是我想要的方式。现在现实赶上,因为我 给使用 要求FrobbleJanitor使用
using。我可以认为这是一个代码审查问题,但是有些困扰我。

问: 将上述被视为滥用的usingIDisposable


阅读 249

收藏
2020-05-19

共1个答案

小编典典

我认为不一定。IDisposable的技术上 指用于事物具有非托管资源,但随后的使用指令是实现的一个常见的模式只是一种巧妙的方法try .. finally { dispose }

一个纯粹主义者会争论“是的,这是侮辱性的”,而在纯粹主义者的意义上是这样。但是我们大多数人不是从纯粹主义者的角度进行编码,而是从一种半艺术的角度进行编码。在我看来,以这种方式使用“使用”构造确实是非常艺术的。

您可能应该将另一个接口放在IDisposable之上,以将其进一步推开,向其他开发人员说明该接口为何暗示IDisposable。

还有许多其他选择可以做到这一点,但最终,我想不出有什么比这更简洁的了,所以去吧!

2020-05-19