- 명시적인 resource 해제를 위한 IDisposable 인터페이스를 구현하고
- using문을 사용하여 object가 관리(생성,사용,삭제)되도록 해야 한다.
public class MyResource: IDisposable{// 외부에서 전달받은 unmanaged 리소스private IntPtr handle;// 내부에서 생성하는 managed 리소스private Component component = new Component();// Dispose가 호출 되었음을 알려주는 flagprivate bool disposed = false;public MyResource(IntPtr handle){this.handle = handle;}// 리소스를 해제하기 위한 method// 하위 class에서 재정의 하지 못하도록 virtual이 아님public void Dispose(){Dispose(true);// object가 위 Dispose메서드 호출로 정리되지만// object가 finalization queue에 포함되어 종료자/finalizer가 호출되지 않도록// 아래 명령어를 호출한다.GC.SuppressFinalize(this);}// 아래 함수가 호출되는 경우는 두가지인데// 첫번째는(disposing == true) 사용자의 코드를 통해 호출되는 경우, 이 때는 managed/unmanaged 리소스를 해제해야 한다.// 두번째는(disposing == false) finalizer가 호출한 상황으로 다른 obejct가 어떤상황인지 모르므로 unmanaged resource만 해제해야 한다.protected virtual void Dispose(bool disposing){if(!this.disposed){if(disposing){// 첫번째 경우 managed 리소스 해제component.Dispose();}// 첫번째, 두번째 경우 unmanaged 리소스 해제CloseHandle(handle);handle = IntPtr.Zero;// dispose가 호출되었음을 기록disposed = true;}}// unmanaged 리소스를 해제하기 위한 interop[System.Runtime.InteropServices.DllImport("Kernel32")]private extern static Boolean CloseHandle(IntPtr handle);// finalization을 위한 종료자/finalizer(소멸자/destructor)// Dispose()가 호출되면 아래 코드는 호출되지 않는다.~MyResource(){Dispose(false);}}
사용자가 Dispose() 호출을 잊어버렸을 때 자원을 해제할 수 있게 한다.
A
Using
block has three parts: acquisition, usage, and disposal.
Acquisition means creating a variable and initializing it to refer to the system resource. The
Using
statement can acquire one or more resources, or you can acquire exactly one resource before entering the block and supply it to theUsing
statement. If you supplyresourceexpression
, you must acquire the resource before passing control to theUsing
statement.Usage means accessing the resources and performing actions with them. The statements between
Using
andEnd Using
represent the usage of the resources.Disposal means calling the Dispose method on the object in
resourcename
. This allows the object to cleanly terminate its resources. TheEnd Using
statement disposes of the resources under theUsing
block's control.
Subclasses should implement the disposable pattern as follows:
They must override
Dispose(Boolean)
and call the base classDispose(Boolean)
implementation.They can provide a finalizer if needed. The finalizer must call
Dispose(false)
.
class DerivedClass : BaseClass{bool disposed = false;SafeHandle handle = new SafeFileHandle(IntPtr.Zero, true);protected override void Dispose(bool disposing){if (disposed)return;if (disposing) {handle.Dispose();// 다른 managed 리소스를 해제}// unmanaged 리소스를 해제disposed = true;// 부모 클래스의 Dispose(bool)를 호출base.Dispose(disposing);}}
종료자/finalizer가 있다면 별도의 대기열에 저장하여 관리하며 종료자/finalizer 호출 전까지 객체가 유지된다.
댓글 없음:
댓글 쓰기