2008-10-21 136 views
2

我有以下类,它在内部使用BinaryReader并实现IDisposable。为什么在BinaryReader上调用Dispose()会导致编译错误?

 
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?

回答

7

由于BinaryReader上的Dispose方法已被明确实施,所以不起作用。

而不是被隐式地实现,如在:

public void Dispose() 
{ 
} 

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

void IDisposable.Dispose() 
{ 
} 

...这意味着它只能通过以下方式访问接口IDisposable。因此,您必须首先将实例投射到IDisposable

+0

完美的例子说明为什么你不应该偏离标准的Dispose模式。 – 2008-10-21 19:01:20

+0

或者只是调用BinaryReader.Close(),它可以做同样的事情。 – 2008-10-21 19:05:50

+1

即便如此,如果你实现了一个Close()方法,它应该完成通常在Dispose()和Dispose()中完成的工作,只需调用Close()即可。无论如何,BinaryReader没有正确地遵循该模式。 – 2008-10-21 19:13:53

3

扩展我的意见here,BinaryReader类没有正确实施Dispose模式。

望着这个类反射器,它看起来像这样(的.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() implementaiton它显式接口迫使开发人员调用Close()代替Dispose()

在这种情况下,我们有一个不平衡的语义的情况。从来没有打电话给“打开”阅读器,因此“关闭”阅读器并不直观。

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

要正确地遵循的模式,它应该被implmented为:

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(...)) 
{ 
} 
1

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

但是Close与dispose完全相同,这是他们希望使用的方法。反射器给出了关闭方法

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

关闭下面拆卸()被使用,因为它是在一个二进制读取的上下文中,更好的选择的话。

相关问题