CA1063: IDisposable을 올바르게 구현하십시오.

속성
규칙 ID CA1063
타이틀 IDisposable을 올바르게 구현하십시오.
범주 디자인
수정 사항이 주요 변경인지 여부 주요 변경 아님
.NET 8에서 기본적으로 사용 아니요

원인

System.IDisposable 인터페이스가 제대로 구현되지 않았습니다. 문제의 가능한 원인은 다음과 같습니다.

  • IDisposable는 클래스에서 다시 구현됩니다.
  • Finalize가 다시 재정의됩니다.
  • Dispose()가 재정의됩니다.
  • Dispose() 메서드가 public이나 sealed나 이름이 Dispose가 아닙니다.
  • Dispose(bool)는 protected거나, virtual이거나, unsealed가 아닙니다.
  • Unsealed 형식의 경우 Dispose()Dispose(true)를 호출해야 합니다.
  • Unsealed 형식의 경우 Finalize 구현은 Dispose(bool) 또는 기본 클래스 종료자 중 하나 또는 둘 다를 호출하지 않습니다.

해당 패턴 중 하나를 위반하면 경고 CA1063이 트리거됩니다.

IDisposable 인터페이스를 선언하고 구현하는 모든 unsealed 형식은 자체 protected virtual void Dispose(bool) 메서드를 제공해야 합니다. Dispose()Dispose(true)를 호출해야 하고 종료자는 Dispose(false)를 호출해야 합니다. IDisposable 인터페이스를 선언하고 구현하는 unsealed 형식을 만드는 경우 Dispose(bool)를 정의하고 호출해야 합니다. 자세한 내용은 관리되지 않는 리소스 정리(.NET 가이드)Dispose 메서드 구현을 참조하세요.

기본적으로 이 규칙은 외부에 표시되는 형식만 확인하지만 이는 구성 가능합니다.

규칙 설명

모든 IDisposable 형식은 Dispose 패턴을 올바르게 구현해야 합니다.

위반 문제를 해결하는 방법

코드를 검사하고 다음 해결 방법을 확인하여 해당 위반을 해결합니다.

  • 형식에 의해 구현된 인터페이스 목록에서 IDisposable을 제거하고 대신 기본 클래스 Dispose 구현을 재정의합니다.

  • 형식에서 종료자를 제거하고 Dispose(bool disposing)를 재정의한 후 ‘disposing’이 false인 코드 경로에 종료 논리를 넣습니다.

  • Dispose(bool disposing)를 재정의한 후 ‘disposing’이 true인 코드 경로에 삭제 논리를 추가합니다.

  • Dispose()가 public 및 sealed로 선언되었는지 확인합니다.

  • Dispose 메서드의 이름을 Dispose로 바꾸고 public 및 sealed로 선언되어 있는지 확인합니다.

  • Dispose(bool)가 protected, virtual, unsealed로 선언되었는지 확인합니다.

  • Dispose(true)를 호출하고 현재 개체 인스턴스(this 또는 Visual Basic에서 Me)에서 SuppressFinalize를 호출한 후 반환되도록 Dispose()를 수정합니다.

  • Dispose(false)를 호출한 후 반환되도록 종료자를 수정합니다.

  • IDisposable 인터페이스를 선언하고 구현하는 봉인되지 않은 형식을 만드는 경우 IDisposable 구현이 섹션 앞부분에서 설명한 패턴을 따르는지 확인합니다.

경고를 표시하지 않는 경우

이 규칙에서는 경고를 표시해야 합니다.

참고

다음이 모두 적용되는 경우 이 규칙에서 가양성 경고가 표시될 수 있습니다.

  • Visual Studio 2022 버전 17.5 이상을 이전 버전의 .NET SDK(.NET 6 이하)와 함께 사용하고 있습니다.
  • .NET 6 SDK 분석기 또는 이전 버전의 분석기 패키지(예: Microsoft.CodeAnalysis.FxCopAnalyzers)를 사용하고 있습니다.
  • IDispose 구현에 특성이 있습니다.

이 경우 가양성 경고가 표시되지 않도록 하는 것이 안전합니다. 가양성은 C# 컴파일러의 호환성이 손상되는 변경으로 인해 발생합니다. 가양성 경고에 대한 수정 사항이 포함된 최신 분석기를 사용하는 것이 좋습니다. Microsoft.CodeAnalysis.NetAnalyzers 버전 7.0.0-preview1.22464.1 이상으로 업그레이드하거나 .NET 7 SDK에서 분석기를 사용하세요.

분석할 코드 구성

다음 옵션을 사용하여 이 규칙이 실행될 코드베이스 부분을 구성합니다.

이 규칙, 적용되는 모든 규칙 또는 적용되는 이 범주(디자인)의 모든 규칙에 대해 이 옵션을 구성할 수 있습니다. 자세한 내용은 코드 품질 규칙 구성 옵션을 참조하세요.

특정 API 화면 포함

접근성을 기반으로 이 규칙을 실행할 코드베이스의 파트를 구성할 수 있습니다. 예를 들어 규칙이 퍼블릭이 아닌 API 표면에서만 실행되도록 지정하려면 프로젝트의 .editorconfig 파일에 다음 키-값 쌍을 추가합니다.

dotnet_code_quality.CAXXXX.api_surface = private, internal

의사 코드 예제

다음 의사 코드는 관리형 리소스와 네이티브 리소스를 사용하는 클래스에서 Dispose(bool)을 구현하는 방법에 대한 일반적인 예를 제공합니다.

public class Resource : IDisposable
{
    private bool isDisposed;
    private IntPtr nativeResource = Marshal.AllocHGlobal(100);
    private AnotherResource managedResource = new AnotherResource();

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

    // The bulk of the clean-up code is implemented in Dispose(bool)
    protected virtual void Dispose(bool disposing)
    {
        if (isDisposed) return;

        if (disposing)
        {
            // free managed resources
            managedResource.Dispose();
        }

        // free native resources if there are any.
        if (nativeResource != IntPtr.Zero)
        {
            Marshal.FreeHGlobal(nativeResource);
            nativeResource = IntPtr.Zero;
        }

        isDisposed = true;
    }

    // NOTE: Leave out the finalizer altogether if this class doesn't
    // own unmanaged resources, but leave the other methods
    // exactly as they are.
    ~Resource()
    {
        // Finalizer calls Dispose(false)
        Dispose(false);
    }
}

참고 항목