본문 바로가기

IT

[C#] using과 Dispose()로 리소스 정리하기


안녕하세요, 모스크바에서 생활하고 있는 개발자 윤진입니다.


C#을 뒤적거리며 보다가 using 구문에 감탄하지 않을 수가 없었습니다.

C는 코딩시작부터 끝까지 메모리 관리에 각별히 신경써야하는데요.

C#의 using은 문제상황에서 알아서 리소스를 정리할 수 있는 메소드를 불러주니,

메모리는 물론 각종 커넥션까지 분명하게 맺고 끊을 수 있겠네요.

원래 예외상황처리로 코드가 지저분해기 마련인데 using이라면 지저분할 일도 적겠죠.


using 구문에 사용하려는 class는,

우선 리소스 정리를 위한 메소드를 만들어두어야 합니다.

- IDisposable interface를 상속하고,

- 리소스 정리를 위한 void Dispose()를 구현해 두어야 합니다.

C#에서는 '인터페이스를 Dispose 패턴으로 구현'할 수 있게 아래와 같은 템플릿을 제공하고 있습니다.


   public class DisposedClass : IDisposable
    {

        #region IDisposable Support
        private bool disposedValue = false; // 중복 호출을 검색하려면

        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    // TODO: 관리되는 상태(관리되는 개체)를 삭제합니다.
                }

                // TODO: 관리되지 않는 리소스(관리되지 않는 개체)를 해제하고 아래의 종료자를 재정의합니다.
                // TODO: 큰 필드를 null로 설정합니다.

                disposedValue = true;
            }
        }

        // TODO: 위의 Dispose(bool disposing)에 관리되지 않는 리소스를 해제하는 코드가 포함되어 있는 경우에만 종료자를 재정의합니다.
        // ~DisposeClass() {
        //   // 이 코드를 변경하지 마세요. 위의 Dispose(bool disposing)에 정리 코드를 입력하세요.
        //   Dispose(false);
        // }

        // 삭제 가능한 패턴을 올바르게 구현하기 위해 추가된 코드입니다.
        public void Dispose()
        {
            // 이 코드를 변경하지 마세요. 위의 Dispose(bool disposing)에 정리 코드를 입력하세요.
            Dispose(true);
            // TODO: 위의 종료자가 재정의된 경우 다음 코드 줄의 주석 처리를 제거합니다.
            // GC.SuppressFinalize(this);
        }
        #endregion


using구문은 다음의 경우에 리소스를 정리할 수 있는 Dispose() 함수를 부릅니다.

1) using 구문이 정상적으로 완료

2) using 구문 수행 중 에러상황이 발생


using의 동작양식은 try - finally와 동일한데,

using 쪽이 보다 편리하고, 보다 빠르게 읽혀집니다.

using (DisposedClass d = new DisposedClass())
{
    d.Print();
}

위의 using 구문은 아래 try-finally 구문과 동일하게 동작합니다.

DisposedClass d = new DisposedClass();
try
{
    d.Print();
}
finally
{
    if (d != null)
        d.Dispose();
}


C#은 개발자를 위해 여러가지를 많이도 준비했군요.