[C#] Dispose와 소멸자 차이

RisingJade의 개발기록·2022년 3월 12일
0

DISPOSE

Dispose 메서드 구현은 주로 관리되지 않는 리소스를 해제하는 데 사용됩니다. IDisposable 구현인 인스턴스 멤버를 사용하는 경우에는 Dispose 호출을 계단식 배열하는 것이 일반적입니다. 예를 들어 할당된 메모리를 해제하거나, 컬렉션에 추가된 항목을 제거하거나, 획득한 잠금 해제를 알리는 등 Dispose를 구현하는 추가적인 이유가 있습니다.

.NET 가비지 수집기는 관리되지 않는 메모리를 할당하거나 해제하지 않습니다. Dispose 패턴이라고도 하는 개체 삭제 패턴에서는 개체의 수명에 순서를 적용합니다. Dispose 패턴은 IDisposable 인터페이스를 구현하는 개체에 사용되며, 파일 및 파이프 핸들, 레지스트리 핸들, 대기 핸들 또는 관리되지 않는 메모리 블록에 대한 포인터와 상호 작용하는 경우 일반적으로 사용됩니다. 이는 가비지 수집기가 관리되지 않는 개체를 회수할 수 없기 때문입니다.
출처: https://docs.microsoft.com/ko-kr/dotnet/standard/garbage-collection/implementing-dispose

using System;

public class Test
{
    public Test()
    {
        Console.WriteLine(" Constructor");
    }
    ~Test()
    {
        Console.WriteLine(" Destructor");
    }
}

public class Program
{
    public static void Main()
    {
        Console.WriteLine("Program Start");
        {
            Test t = new Test();
            Console.WriteLine("  Do with Test");
        }
        Console.WriteLine("Program End");
    }
}
___________console
Program Start
 Constructor
  Do with Test
Program End
 Destructor

위의 예시를 보자 소멸자가 호출되긴 하는데, 그 시점이 프로그램 종료된 후 이다.

C#의 경우 t 객체는 힙(heap) 위에 동적할당의 형태로 잡힌다. 그 말인 즉슨, 일반적인 로컬 변수들이 저장되는 스택과는 달리 해제될 시점을 알 수 없다는 것.

C#에서는 메모리관리를 프로그래머가 아니라 시스템(Gabage Collection)에서 하므로 메모리 해제할 시점을 프로그래머가 확정할 수 없다. 위 예제에서처럼 프로그램 종료할 때라든지, 아니면 메모리가 부족해져 가비지 콜렉션을 할때 실행된다.

이때! 내가 즉각적으로 해당 데이터를 힙에서 제거하고 싶으면 Dispose를 이용한다!.

위와 같은 경우 C#에서는 소멸자 대신 Dispose를 사용하는 것이 좋다.

using System;

public class Test : IDisposable
{
    public Test()
    {
        Console.WriteLine(" Constructor");
    }
    public void Dispose()
    {
        Console.WriteLine(" Dispose");
    }
}

public class Program
{
    public static void Main()
    {
        Console.WriteLine("Program Start");
        using(Test t = new Test())
        {
            Console.WriteLine("  Do with Test");
        }
        Console.WriteLine("Program End");
    }
}
____________console
Program Start
 Constructor
  Do with Test
 Dispose //먼저  DISPOSE가 호출된다.
Program End

PS.

  • Dispose는 인터페이스인 IDisposable의 멤버이므로 반드시 public으로 정의되어야 한다.

  • using문에서 선언된 객체는 using블럭을 빠져나갈때 그 객체의 Dispose() 메소드를 호출한다. 그러므로 Dispose()로서 소멸자와 동일한 효과(느낌적으로 괄호를 벗어나면 사라지는 것 같은...) 를 낼 수 있다.

  • 그냥 C#에서 소멸자를 정의하고 동적할당을 해서 생성한뒤 명시적으로 Dispose()를 호출하지 않으면 GC가 돌다가 관리가 안되는 객체임을 알고 삭제시키는데 이때 소멸자가 작동되고 그 소멸자 안에서 자동으로 Dispose()가 호출되는 형식이다.

    출처: https://chamsol6.blogspot.com/2017/07/c-dispose.html

profile
언제나 감사하며 살자!

0개의 댓글