2008-10-21 4 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); 
     } 
    } 

것은 이미 내가 그것을 폐기를 호출 할 수는 IDisposable에 BinaryReader를 캐스팅 할 필요가 있다고 생각,하지만 난 그냥 캐스팅하지 않고 직접) 방법을 폐기 (호출 할 수 없습니다 왜 이해가 안 돼요 IDisposable에?

답변

7

BinaryReaderDispose 메서드가 명시 적으로 구현 되었기 때문에 작동하지 않습니다. 그 대신에 암시 적으로 구현 될

는 : 그것은 통해서만 액세스 될 수 있음을 의미 ...

void IDisposable.Dispose() 
{ 
} 

:

public void Dispose() 
{ 
} 

... 명시 같이 구현 된 IDisposable 인터페이스 따라서 먼저 인스턴스를 IDisposable으로 캐스팅해야합니다.

+0

표준 Dispose 패턴에서 벗어나지 않아야하는 완벽한 예입니다. –

+0

또는 동일한 작업을 수행하는 BinaryReader.Close()를 호출하십시오. –

+1

그렇다고하더라도 Close() 메서드를 구현하면 Dispose() 및 Dispose()에서 수행 한 작업이 Close()를 호출해야합니다. BinaryReader는 패턴을 제대로 따르지 않았습니다. –

3

내 의견 here에 확장하면 BinaryReader 클래스가 Dispose 패턴을 올바르게 구현하지 못합니다. 리플렉터에서이 클래스에서 찾고

, 그것은 다음과 같습니다 (.NET 3.5) : 그것은 implementaiton 명시 적 인터페이스 개발자를 강제 IDisposable.Dispose()함으로써

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); 
    } 
} 

문제는 여기에 대신 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(); 
    } 
} 

이 당신이있는 경우 중 하나를 호출 Dispose(true)를 호출 결과 계속 Close() 또는 Dispose(), 중 하나를 호출 할 수 것입니다 :

제대로 패턴을 따라하기 위해서는으로 implmented되어 있어야합니다. (Close() 또는 ((IDisposable)reader).Dispose()을 호출하여 실제 구현과 동일한 흐름입니다.

다행스럽게도 (또는 불행하게도, 당신이 그것을보고 선택하는 방법에 따라) BinaryReader 그것이 using 문에 허용되는 IDisposable 인터페이스 구현 않기 때문에 : 사실

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

"Dispose (bool)을 직접 호출 할 수있는 옵션이 있습니다."- 보호되어 있으므로 옵션이 아닙니다. –

+0

@Mark, 귀하의 의견은 스스로 모순됩니다 ... Dispose (bool)는 BinaryReader를 상속하지 않는 한 직접 액세스 할 수 없도록 보호되어 있습니다 (BinaryReader는 사용법에 따라 옵션이 될 수 있음). –

1

그들이 닫기를 사용하기로 선택한를 () 대신 Dispose() Dispose가 명시 적으로 구현되었습니다. 그래서 당신이 그것을 볼 수없는 이유입니다.

그러나 닫기는 처리와 동일한 작업을 수행하며, 사용자가 사용하기를 원하는 방법입니다.반사판은 바이너리 독자의 맥락에서 단어의 더 나은 선택이기 때문에 사용되는 Close 메서드

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

닫기에 대해 다음과 분해()를 제공합니다.

+0

그들이이 길로 내려간 이유는 무엇입니까? – Damien

관련 문제