为什么在BinaryReader上调用Dispose()会导致编译错误?

时间:2008-10-21 18:48:31

标签: c# .net

我有以下类在内部使用BinaryReader并实现IDisposable。

class DisposableClass : IDisposable
    {
        private BinaryReader reader;
        public DisposableClass(Stream stream)
        {
            reader = new BinaryReader(stream);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                ((IDisposable)reader).Dispose();
//                reader.Dispose();// this won't compile
            }
        }

        public void Dispose()
        {
            this.Dispose(true);
        }
    }

我已经发现我需要将BinaryReader转换为IDisposable以便能够在其上调用Dispose,但我不明白为什么我不能直接调用Dispose()方法而不转换为IDisposable?< / p>

3 个答案:

答案 0 :(得分:7)

它无效,因为Dispose上的BinaryReader方法已明确实施。

而不是隐式实现,如:

public void Dispose()
{
}

......已明确实施,如:

void IDisposable.Dispose()
{
}

...这意味着它只能通过IDisposable界面访问。因此,您必须先将实例强​​制转换为IDisposable

答案 1 :(得分:3)

扩展我的评论hereBinaryReader类未正确实现Dispose模式。

在Reflector中查看此类,它看起来像这样(对于.NET 3.5):

public class BinaryReader : IDisposable
{
    public virtual void Close()
    {
       this.Dispose(true);
    }
    protected virtual void Dispose(bool disposing)
    {
       if (disposing)
       {
          Stream stream = this.m_stream;
          this.m_stream = null;
          if (stream != null)
          {
             stream.Close();
          }
       }
       this.m_stream = null;
       this.m_buffer = null;
       this.m_decoder = null;
       this.m_charBytes = null;
       this.m_singleChar = null;
       this.m_charBuffer = null;
   }
   void IDisposable.Dispose()
   {
      this.Dispose(true);
   }
}

这里的问题是,通过使IDisposable.Dispose()显式接口实现,它会迫使开发人员调用Close()而不是Dispose()

在这种情况下,我们有一个不平衡语义的例子。从来没有打电话给读者“打开”,所以“关闭”读者并不直观。

更进一步,为了调用Dispose(),你必须明确地转换为IDisposable,这不是你通常需要做的事情。您可以选择直接调用Dispose(bool),但是您如何知道布尔参数应该是什么?

要正确遵循该模式,它应该被表示为:

public class BinaryReader : IDisposable
{
    public virtual void Close()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    protected virtual void Dispose(bool disposing)
    {
       if (disposing)
       {
          Stream stream = this.m_stream;
          this.m_stream = null;
          if (stream != null)
          {
             stream.Close();
          }
       }
       this.m_stream = null;
       this.m_buffer = null;
       this.m_decoder = null;
       this.m_charBytes = null;
       this.m_singleChar = null;
       this.m_charBuffer = null;
   }
   public void Dispose()
   {
      this.Close();
   }
}

这样您就可以拨打Close()Dispose(),在这种情况下,任一呼叫都会继续调用Dispose(true)。 (这与实际实现的流程相同,只需调用Close()((IDisposable)reader).Dispose())。

幸运的是(或者不幸的是,取决于您选择查看它的方式),因为BinaryReader确实实现了IDisposable接口,因此在using语句中允许使用它:

using (BinaryReader reader = new BinaryReader(...))
{
}

答案 2 :(得分:1)

实际上他们选择使用Close()而不是Dispose() Dispose已经明确实现。这就是为什么你看不到它。

然而,Close与dispose的作用相同,这是他们希望您使用的方法。 Reflector为Close方法

提供以下反汇编
public virtual void Close()
{
    this.Dispose(true);
}

使用Close()是因为它是二进制阅读器上下文中更好的单词选择。