destructor / Dispose()

C#, .NET 2011. 6. 17. 19:23
1.소멸자가 호출되는 시점
GC에 의해 객체가 메모리 해제를 당하기 직전

참고 : C++ 에서는 GC가 없기때문에 컴파일러가 소멸자를 호출하는 코드를 삽입한다.
객체가 정적으로 할당되었다면 객체가 속한 scope가 끝날 때 호출할 것이고 
동적으로 할당되었다면(new 키워드로) delete로 객체를 소멸시킬때 호출될 것이다.

2.Dispose()가 (자동으로) 호출되는 시점
Dispose()는 using 문이 끝날 때 자동으로 호출된다.
혹은 using 문 안에서 객체에 대한 참조카운트가 0 이 되거나 하여도 호출된다.
(사실 using 문이 끝나면 참조카운트가 0 이 되는 셈이다)


IDisposable을 구현하는 객체에 using 문을 사용했다면 Dispose()가 먼저 호출되고, 소멸자가 호출된다.

소멸자에서 객체의 멤버를 사용하여 무언가를 하려고 들면 안된다.

만약 객체가 소멸하기전에 (자동으로) 자신을 직렬화하여 저장하고 싶다거나 하면 소멸자가 아니라 Dispose() 에서 해야한다.
(물론 객체는 IDisposable 을 구현해야 하고, 반드시 using 을 사용하도록 한다.)

서로가 서로를 참조하는 객체가 있을 경우 (A,B 라고 하자)

A,B 에 대한 참조카운트가 각각 0 이 되어 A,B는 GC의 타겟이 되었을 때

만약 B가 먼저 GC를 당한다면

A의 소멸자에서 직렬화를 하여 저장하려고 하면 A가 가진 B의 참조는 null 이 되기 때문이다.

(headfirst C# p674 참고)


결론
C#의 소멸자에서는 왠만하면 아무일도 하지 말자.(이유 : 상호참조로 인하여 내부 멤버가 온전하지 않을 수 있음)
객체가 소멸하기 직전 뭔가를 하고 싶다면 IDisposable을 구현하여 Dispose()에서 하도록 하고, 반드시 using 문을 사용하도록 하자.

내생각 : GC가 없는 C++ 에서는 어떤가?
scope가 끝날때 컴파일러에 의해 삽입된 소멸자 호출 코드가 실행되는데..
뭐가 더 먼저 불려질거란 것을 확신할 수 없으니 C++에서도 마찬가지 문제가 생길듯.
new,delete 로 수동으로 메모리 해제를 해준다면 귀찮기는 하겠지만 괜찮아 지긴 할듯.


**참고 : 소멸자는 .NET이 직접 다룰수 없는 윈도우 핸들 등을 적절히 처리하는 일을 한다. 그래서 의미가있다..
(headfirst C# p676)

'C#, .NET' 카테고리의 다른 글

확장 메소드와 static class  (0) 2011.06.17
struct  (0) 2011.06.17
Form 과 관련된 여러가지 속성 등  (0) 2011.06.17
컨트롤과 Dispose()  (0) 2011.06.17
ref 와 out  (0) 2011.06.17
Posted by 휘사마
,