문제

나는 idisposable을 구현하는 추상적 인 수업이 있습니다.

public abstract class ConnectionAccessor : IDisposable
{
    public abstract void Dispose();
}

Visual Studio 2008 팀 시스템에서는 프로젝트에 대한 코드 분석을 실행했으며 등장한 경고 중 하나는 다음과 같습니다.

Microsoft.Design : 'ConnectionAccessor.dispose ()'를 수정하여 Dispose (true) 호출을 한 다음 현재 객체 인스턴스에서 GC.SuppressFinalize ( 'this'또는 'me')에서 호출 한 다음 반환합니다.

단지 어리석은가, 추상적 인 방법의 본문을 수정하라고 말하거나, 어떤 인스턴스에서나 더 이상 무언가를해야합니까? Dispose?

도움이 되었습니까?

해결책

구현을위한 기존 패턴을 따라야합니다 Dispose. 만들기 Dispose() 기존 패턴은 "관리 된 정리"(API 클라이언트 호출 Dispose() 직접 또는 경고 using) 및 "관리되지 않은 정리"(GC Calling Finalizer). 상기시키기 위해, 패턴은 다음과 같습니다.

public class Base
{
    ~Base()
    {
        Dispose(false);
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this); // so that Dispose(false) isn't called later
    }

    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
             // Dispose all owned managed objects
        }

        // Release unmanaged resources
    }
}

여기서 핵심은 Finalizer와 사이에 중복이 없다는 것입니다. Dispose 관리되지 않는 정리의 경우, 그러나 파생 된 클래스는 관리 및 관리되지 않는 청소를 모두 확장 할 수 있습니다.

당신의 경우에, 당신이해야 할 일은 다음과 같습니다.

protected abstract void Dispose(bool disposing)

그리고 다른 모든 것을 그대로 두십시오. 파생 된 클래스를 시행하여 구현하기 때문에 그것은 모호한 가치가 있습니다. Dispose 이제 - 그리고 그들 모두가 그것을 필요로한다는 것을 어떻게 알 수 있습니까? 기본 클래스에 폐기 할 것이 없지만 대부분의 파생 클래스가 (몇 가지 예외를 제외하고) 비우기 만하면 빈 구현 만 제공 할 수 있습니다. 그것은 무엇입니다 System.IO.Stream (그 자체는 초록)이므로 선례가 있습니다.

다른 팁

경고는 기본적으로 당신에게 그것을 구현하라고 지시합니다 패턴 처리 당신의 수업에서.

결과 코드는 다음과 같아야합니다.

public abstract class ConnectionAccessor : IDisposable
{
    ~ConnectionAccessor()
    {
        Dispose(false);
    }

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

    protected virtual void Dispose(bool disposing)
    {
    }
}

지금까지 제공된 답변으로 가질 수있는 유일한 그립은 그들이 모두 당신이 당신을 가정한다는 것입니다. 필요 파이널 라이저를 갖는 것은 반드시 그런 것은 아닙니다. 마무리와 관련된 상당히 중요한 성능 오버 헤드가 있으며, 필요하지 않은 경우 파생 된 클래스에 부과하고 싶지 않습니다.

보다 이 블로그 게시물 결승전제가 필요하거나 필요하지 않을 수있는시기와 어느 경우에도 처분 패턴을 올바르게 구현하는 방법을 설명하는 Joe Duffy.
Joe의 블로그 게시물을 요약하면, 관리되지 않는 메모리를 다루는 상당히 낮은 수준의 일을하지 않으면 최종화기를 구현해서는 안됩니다. 일반적으로 클래스가 idisposable 스스로를 구현하는 관리 유형에 대한 참조 만 보유한 경우 최종화기가 필요하지 않지만 해당 리소스를 구현하고 해당 리소스를 폐기해야합니다). 코드 (Pinvoke?)에서 직접 관리되지 않는 리소스를 할당하고 해당 리소스를 해제 해야하는 경우 필요한 자원이 필요합니다. 파생 클래스는 실제로 필요한 경우 파이널 라이저를 추가 할 수 있지만, 기본 클래스에 넣어 모든 파생 클래스를 최종화기를 강요하면 오버 헤드가 없을 때 최종화 가능한 객체의 성능에 의해 모든 파생 클래스가 영향을받습니다. 필요한.

Nit-Picking과 비슷한 것처럼 보이지만 조언은 유효합니다. 당신은 이미 ConnectionAccessor의 하위 유형이 무엇 그들이 처분해야 할 필요가 있습니다. 따라서 각 하위 유형에 의존하지 않고 기본 클래스에 의해 적절한 정리가 수행되는 것이 기본 클래스에 의해 수행되는 것이 더 나은 것처럼 보입니다.

나는 Bruce Wagners Book에서 언급 된 처분 패턴을 사용합니다. 효과적인 C# 기본적으로 :

public class BaseClass : IDisposable
{
    private bool _disposed = false;
    ~BaseClass()
    {
        Dispose(false);
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(true);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (_disposed)
            return;

        if (disposing)
        {
            //release managed resources
        }

        //release unmanaged resources

        _disposed = true;
    }
}

public void Derived : BaseClass
{
    private bool _disposed = false;

    protected override void Dispose(bool disposing)
    {
        if (_disposed) 
            return;

        if (disposing)
        {
            //release managed resources
        }

        //release unmanaged resources

        base.Dispose(disposing);
        _disposed = true;
    }

그래도 경고는 흥미 롭습니다. C# 디자이너 중 하나 인 Eric Lippert는 오류 메시지가 "진단이지만 규범이 아님 : 솔루션이 아닌 문제를 설명"해야하는 이유에 대해 블로그를 작성했습니다.여기를 읽으십시오.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top