C# 관리되지 않는 객체(unmanaged) 해제하기 위한 using 문 사용하기

C# & MFC

C# 관리되지 않는 객체(unmanaged) 해제하기 위한 using 문 사용하기

 

환경: Microsoft Visual Studio 2013

 

클래스의 인스턴스가 런타임 환경에서 캡슐화 되는 경우 이를 해제할 방법이 필요합니다. 이것을 관리되지 않는(unmanaged) 자원 이라고 합니다. 관리되지 않는 자원이란 윈도우 시스템 자원을 말합니다. 예를 들어 List 같은 메모리 자원은 관리되는 자원이며 핸들 관련 시스템 자원은 관리되지 않는 자원입니다. 이런 관리되지 않는 자원을 해제해 몇 가지 패턴에 대해 알아 보겠습니다. 

 

우리가 객체를 해제 할 때 아래 샘플처럼 Close() 함수를 호출해도 됩니다. 하지만 에러가 발행하면 어떻게 될까요? file.txt 파일이 없는 경우 객체를 생성하는 순간에 중단되어서 reader.Close() 함수는 호출되지 않습니다. 이런 실수를 방지하기 위해 using try catch finally 문을 사용합니다.  

var reader = new StreamReader("file.txt");
var content = reader.ReadToEnd();
// Do something with content
reader.Close();

 

모든 관리되지 않는 자원은 IDisposable 인터페이스를 상속 받아 구현해 놓았습니다. 그래서 직접 base 클래스를 구현하지 않고 Dispose 함수만 호출해 주면 됩니다. 첫 번째로 관리되지 않는 자원을 해제할 때 using 문을 사용하는 것입니다. using try finally 블록을 대신해서 사용하는 것입니다. using scope 를 벗어나는 순간 Dispose() 함수를 자동으로 호출하게 됩니다.

using System;
using System.Text;
using System.IO;
using System.Text.RegularExpressions;

namespace DisposeSample
{
    class Program
    {
        static void Main(string[] args)
        {
            WordInfo wc = new WordInfo("file.txt");
            int count = wc.Count;
        }

        public class WordInfo
        {
            private String filename = String.Empty;
            private int nWords = 0;
            private String pattern = @"\b\w+\b";

            public WordInfo(string filename)
            {
                if (!File.Exists(filename))
                    throw new FileNotFoundException("파일이 존재하지 않습니다.");

                this.filename = filename;
                string txt = String.Empty;

                using (StreamReader sr = new StreamReader(filename))
                {
                    txt = sr.ReadToEnd();
                }
                nWords = Regex.Matches(txt, pattern).Count;
            }

            public string FullName
            { get { return filename; } }

            public string Name
            { get { return Path.GetFileName(filename); } }

            public int Count
            { get { return nWords; } }

        }   
    }
}

 

다음은 using 이 아닌 try catch finally 문을 사용해 보겠습니다. finally 영역에 시스템 객체를 해제 하기 위한 Dispose() 함수를 넣었습니다. 위의 코드와 비교해 봤을 때 조금 더 복잡하죠. 그래서 심플하고 가독성 있는 소스를 만들기 위해 using 문을 많이 사용합니다.

using System;
using System.Text;
using System.IO;
using System.Text.RegularExpressions;

namespace DisposeSample
{
    class Program
    {
        static void Main(string[] args)
        {
            WordInfo wc = new WordInfo("file.txt");
            int count = wc.Count;
        }

        public class WordInfo
        {
            private String filename = String.Empty;
            private int nWords = 0;
            private String pattern = @"\b\w+\b";

            public WordInfo(string filename)
            {
                if (!File.Exists(filename))
                    throw new FileNotFoundException("파일이 존재하지 않습니다.");

                this.filename = filename;
                string txt = String.Empty;
                StreamReader sr = null;
                try
                {
                    sr = new StreamReader(filename);
                    txt = sr.ReadToEnd();
                }
                finally
                {
                    if (sr != null) sr.Dispose();
                }
                nWords = Regex.Matches(txt, pattern).Count;
            }

            public string FullName
            { get { return filename; } }

            public string Name
            { get { return Path.GetFileName(filename); } }

            public int Count
            { get { return nWords; } }

        }   
    }
}
저작자 표시 비영리 변경 금지
신고
Posted by 녹두장군