2010-01-13 4 views
8

나는 다음과 같은 클래스 지금IDisposable을 사용하여 이벤트 구독 취소 - 다른 물건을 처분해야합니까?

public class Presenter: IDisposable 
{ 
    public IView View 
    {get;private set;} 

    //snip other object reference, all managed 
    public Presenter(IView view) 
    { 
    View=view; 
    View.MouseUp += MouseUpEvent; 
    } 

    public void MouseUpEvent() 
    { 
    //do whatever you want to do on mouse up 
    } 

    public void Dispose() 
    { 
    View.MouseUp -= MouseUpEvent; 
    // no more manual disposing 
    } 
} 

문제는, 내가 제대로 Dispose() 방법을 구현하고있다? 또는 Dispose()을 명확하게 정의했기 때문에 다른 모든 관리 대상을 수동으로 처리해야합니까?

GC는 수동으로 수행하지 않아도 자체적으로 처리 (이벤트 구독 제외) 할 수 있다고 생각합니다. 내가 맞습니까?

답변

8

생성자를 구독하는 선택의 여지가 있다면 합리적입니다. Josh의 감정을 반향시키는 것이 최선의 방법이 아닐 수도 있습니다. 반면에, 그것은 항상 좋은 일인 당신의 목표를 달성하는 가장 간단한 방법 일 수 있습니다. 나는 UI 패턴에 대한 전문가 인 척하지 않을 것이다. 우려를 제기하면서, 나는 이것이 당신이 일하기를 원하는 방식이라고 가정하고, 그 질문 자체를 다룬다. :)

개인적으로 Josh의 처방을 찾는다. 패턴 은 단순한 시나리오에서 지나치게 복잡합니다. 단 하나의 변화만으로 접근 방식이 적절합니다. 즉, 클래스를 봉인하십시오. 클래스를 봉인하지 않으려면 Dispose(bool) 옵션 (하지만 finalizer는 없음)으로 가야합니다. 서브 클래스도 처리해야 할 수도 있고 finalizer가 필요할 수도 있기 때문입니다. 파생 된 유형의 가능성이 없으면 인생은 더 쉬워집니다 (자주 그렇듯이).

은 이제 그 이유 중 하나로 IDiposable을 구현했기 때문에 다른 구성원과 아무 것도 할 필요가 없습니다.

그래서이 클래스에서 더 이상 파생해야합니까?


1 난 당신이 더 자세한 내용은 Joe Duffy et al의 조언을 읽어 볼 것을 권하고 싶습니다하지만 나는,이 표준 권장 패턴임을 이해한다 - 그것은 모두 매우 복잡를 얻을 수 있습니다.

+0

나는 그것이 필요할 것이라고 생각하지 않는다. 아인슈타인의 답을 받아 들였습니다. 나는 당신을 이해하기 쉽기 때문에 (모든 필사자가 아인슈타인을 이해할 수있는 것은 아닙니다 :)). – Graviton

+0

하위 주제가 없어도 클래스가 봉인되지 않으면 하위 클래스가있을 수 있으므로 관리되지 않는 리소스를 구체적으로 보유하지 않아도 finalizer가 있어야합니다 (구성 요소의 경우와 같이). 기본 클래스가 Finalization시 Dispose (bool) 호출을 담당하는지 여부를 알아야합니다. 그러나 나는 내가 주제에서 벗어나고 있다고 말했다. – Josh

+0

@Josh : 클래스에 파이널 라이저가 필요한 경우, 파이널 라이저를 구현하고 'Dispose (false)'를 호출해야한다고 생각합니다. 어쨌든'Dispose'는 여러 번 호출 할 수 있어야합니다. 불필요한 파이널 라이저가있는 클래스를로드하는 것보다 낫습니다. 파이널 라이저는 요즘은 거의 없어야하지만 (SafeHandle' 외), 실제 성능 비용이 있습니다. –

5

개인적으로 저는 생성자에서 이벤트 후크/언 후크를 피하고 처리하지 않을 것입니다. 대신보기 가져 오기/설정 접근 자에 코드를 추가하고 거기에 추가합니다. 그러나 뷰가 부착되어있는 상태에서 발표자가 처분되면 나는 그것을 정리하려고 노력하지 않을 것입니다. 명시 적으로 분리해야하는 경우 명시 적으로 발표자에서보기를 분리 할 수 ​​있습니다.

그런데, 여기 내가 IDisposable에 대해 알고있는 것이 있습니다.

implementing IDisposable에 대한 권장 접근법은 조치를 취한 곳에서 보호 된 Dispose (bool) 메소드를 사용하는 것입니다. 그 이유는 명시 적 처분과 종료 (가비지 수집)로 인한 처분을 구별하고자하기 때문입니다.

명시 적 Dispose() 호출로 인해 처분 될 때 관리 대상을 만지는 것이 좋으며 당신이 만든 것도 처분해야 할 처분이 예상됩니다. 따라서 처분 = true 일 때만 이것을 수행합니다.

누군가가 (당신이) Dispose를 호출하지 못하고 파이널 라이저가 호출 된 경우, 가비지 수집 (disposing = false) 후에 처리되고 관리 대상 객체를 처리하지 않으려 고하기 때문에 이미 마무리되었을 수 있습니다 . 이 경우에 해제해야 할 것은 Win32 핸들과 같은 관리되지 않는 리소스뿐입니다.

마지막으로 Dispose()를 명시 적으로 호출하면 가비지 수집기의 성능 힌트 인 GC.SupressFinalize (this)가 표시됩니다. 개체를 수집 할 때 개체를 완성 할 필요가 없다는 것을 알 수 있습니다. 완료는 저렴하지 않습니다.

class MyObject : IDisposable { 

    ~MyObject() { 
     Dispose(false); 
    } 

    public void Dispose() { 
     Dispose(true); 
     GC.SupressFinalize(this); 
    } 

    protected virtual void Dispose(bool disposing) { 
     if (disposing) { 
      // dispose of managed resources 
     } 
     // dispose of unmanaged resources 
    } 

} 
+3

클래스가 관리되지 않는 리소스를 보유하지 않는 한 finalizer ('~ MyObject() {Dispose (false);}')를 추가하지 않으려합니다. 이 경우 'SafeHandle'에 관리되지 않는 리소스 핸들을 래핑하는 것이 좋습니다. 일반적으로'IDisposable'을 구현하는 잘 디자인 된 객체는'CriticalFinalizerObject'에서 파생되거나 finalizer를 가지지 않습니다. –

+0

마무리 자에 대한 아주 좋은 점. – Josh