In to the C# 2014. 1. 14. 16:17

Dispose in C#

C#은 Garbage Collector에 의해 Heap메모리를 관리하고 있습니다.

C나 C++ 처럼 메모리 해제를 프로그래머가 대신 해줄 수는 없습니다. 구글에 C#에서 인스턴스 해제를 어떻게 하냐는 질문에는 Dispose를 구현하라 라고 나와있는 글들이 많습니다.


그러나 Dispose패턴은 메모리 해제와 관련이 없습니다. Dispose의 정보가 상당히 와전된 경우 입니다. 저도 그렇게 알고 있었는데 다시 찾아보니 그게 아니더군요.


Dispose의 사전전 의미로는 처분하다/처리하다/폐기하다 라는 뜻으로 왠지 메모리 해제와도 관련이 있어 보이긴 합니다.


이제 자세히 알아보겠습니다.

Dispose의 구현은 대게 Close나 Dispose 멤버 메소드를 갖고 있는 인스턴스를 멤버로 갖고 있을 때 구현해주어야 합니다. 즉, 런타임중 관리되지 않는 핸들, 데이터베이스 연결등 리소스에 대한 제어를 명시적으로 해주기 위함입니다. (Finalize 구현으로 암시적으로 수행할 수도 있습니다.)


명시적으로 리소스를 정리하기 위해서는 Dispose를 구현하여야 합니다. 예제를 보겠습니다.


DisposeableObject는 Stream을 멤버로 보유하고 있습니다. 우리는 DisposeableObject를 다 쓴 경우 Stream의 핸들을 해제 시켜주어야 합니다. 그래서 명시적으로 DisposeableObject는 Dispose를 구현하도록 만들어 준 것입니다. 


그리고 Line 43에 보면 GC.SuppressFinalize를 호출합니다. 이것은 Finalize가 호출 되지 않도록 막은 것입니다. MSDN에서는 GC.SuppressFinalize를 호출하기를 권장합니다. 단, Finalize에서 호출되어야 하는 패턴이 존재한다면 이 규칙은 적용되지 않습니다. 

DisposeableObject를 다 사용한 경우 Dispose 메소드를 호출하는 것이 가장 이상적입니다.


위 내용을 요약하면 멤버 객체중에 Close, Dispose메소드를 갖고 있는 경우 Dispose를 구현하라는 내용입니다. 


추가  : Close와 Dispose의 개념적 차이

한줄로 표현한다면 Close된 객체는 재사용이 가능하고, Dispose된 객체는 재사용이 불가능 하다고 생각하면 됩니다. 단 Close에서 Dispose를 호출한다면 이또한 사용할 수 없겠죠.


추가2 : 그럼 메모리 해제는?

Garbage Collector가 알아서 잘할테니 건드리지 마세요.