|
class A : IDisposable { public void Dispose() { Console.WriteLine("A Dispose()"); } }
class B : IDisposable { public void Dispose() { Console.WriteLine("B Dispose()"); } }
using (A a = new A()) { using (B b = new B()) {
} } |
=>이 코드를 Code Analysis을 통해서 Analyze 해보면 "No code analysis issues were detected." 라고 나온다.
|
using (MemoryStream ms = new MemoryStream()) { using (StreamReader reader = new StreamReader(ms)) {
} } |
=>요 코드를 돌려보면 "Do not dispose objects multiple times" 라고 나온다.
얼핏 보면 IDisposable을 구현한 클래스들에 대해서는 각각의 Dispose()을 호출하는 것이 옳다고 보이나(using을 사용하면 마지막 } 에서 Dispose()가 호출 됨) Code Analysis가 위와 같은 결과를 알려줬으므로 우리는 StreamReader가 내부적으로 어떻게 작동하는지 확인해볼 필요가 있다.
StreamReader는 TextReader을 상속 받았고, TextReader의 Dispose()에서는 Dispose(bool disposing)를 호출 하도록 되어 있다.
|
public void Dispose() { this.Dispose(true); GC.SuppressFinalize(this); } |
이 Dispose(bool disposing)은 다시 virtual 메서드로 StreamReader에서 override 되었다.
StreamReader의 Dispose(bool dispoing)을 보면 다음과 같이 구현이 되어 있다.
|
protected override void Dispose(bool disposing) { try { if ((!this.LeaveOpen && disposing) && (this.stream != null)) { this.stream.Close(); } } finally { if (!this.LeaveOpen && (this.stream != null)) { this.stream = null; this.encoding = null; this.decoder = null; this.byteBuffer = null; this.charBuffer = null; this.charPos = 0; this.charLen = 0; base.Dispose(disposing); } } } |
넘겨진 stream의 close()을 호출해주고 있다. 그렇다면 Stream의 close을 보도록 하자.
|
public virtual void Close() { this.Dispose(true); GC.SuppressFinalize(this); } |
Dispose(true)을 호출하게 되어있다. 이 Dispose(bool disposing)은 virtual로 되어있다.
MemoryStream의 Dispose(bool dispoing)을 보도록 하자.
|
protected override void Dispose(bool disposing) { try { if (disposing) { this._isOpen = false; this._writable = false; this._expandable = false; this._lastReadTask = null; } } finally { base.Dispose(disposing); } } |
머 이런저런 내용들을 정리해주고 있다.
급작스럽겠지만 MemoryStream의 Dispse()을 보면 다음과 같다.
|
public void Dispose() { this.Close(); } |
아까 위에서 봤던 this.Close()을 호출해주고 그 뒤로는 똑같은 작업을 다시 하게 된다.
여기까지 본다면 사실 상 MemoryStream의 Close()는 StreamReader가 1번 자신의 Dispose()에서 1번 총 2번 호출되게 된다. 하지만 Dispose() 자체가 2번 호출되지는 않는데 어째서 Analyze 결과에는 아까와 같은 내용을 보여주는지는 모르겠다. ㅠㅠ
아무튼 앞에서 보았던 코드를 다음과 같이 수정을 한다면 아무런 문제가 없다고 나오게 된다.
|
MemoryStream ms = new MemoryStream(); using (StreamReader reader = new StreamReader(ms)) {
} |
결과는 "No code analysis issues were detected." ~_~
그렇다면 결국 ms의 해제는 StreamReader에게 맡겨도 되는 것인가? 애매하다 -_-..;;