수색…


비고

  • IDisposable 을 구현하는 클래스의 클라이언트는 개체를 사용하여 마쳤을 때 Dispose 메서드를 호출해야합니다. Dispose 메서드를 호출 할 개체를 직접 검색하는 것은 CLR에 없습니다.

  • 개체에 관리되는 리소스 만있는 경우에는 finalizer를 구현할 필요가 없습니다. 자신의 Dispose 메소드를 구현할 때 클래스가 사용하는 모든 객체에서 Dispose 를 호출해야합니다.

  • 이상적으로 한 번만 호출해야하지만 Dispose 에 대한 여러 번 호출에 대해 클래스를 안전하게 만들 것을 권장합니다. 이것은 클래스에 private bool 변수를 추가하고 Dispose 메서드가 실행될 때 값을 true 설정하여 수행 할 수 있습니다.

관리되는 리소스 만 포함하는 클래스

관리 자원은 런타임의 가비지 컬렉터가 알고 있고 통제하고있는 자원입니다. BCL에는 예를 들어 관리되지 않는 리소스의 래퍼 클래스 인 SqlConnection 과 같은 많은 클래스가 있습니다. 이 클래스는 이미 IDisposable 인터페이스를 구현합니다. 완료되면 코드를 정리해야합니다.

클래스에 관리되는 리소스 만 포함되어있는 경우에는 finalizer를 구현할 필요가 없습니다.

public class ObjectWithManagedResourcesOnly : IDisposable
{
    private SqlConnection sqlConnection = new SqlConnection();

    public void Dispose()
    {
        sqlConnection.Dispose();
    }
}

관리되는 리소스와 관리되지 않는 리소스가있는 클래스

마무리 작업을 통해 관리되는 리소스를 무시하는 것이 중요합니다. 파이널 라이저는 다른 스레드에서 실행됩니다. 파이널 라이저가 실행될 때 관리 대상 객체가 더 이상 존재하지 않을 수도 있습니다. 보호 된 Dispose(bool) 메서드를 구현하는 것은 관리되는 리소스에 Finalizer에서 호출 된 Dispose 메서드가 없도록하는 일반적인 방법입니다.

public class ManagedAndUnmanagedObject : IDisposable
{
    private SqlConnection sqlConnection = new SqlConnection();
    private UnmanagedHandle unmanagedHandle = Win32.SomeUnmanagedResource();
    private bool disposed;

    public void Dispose()
    {
        Dispose(true); // client called dispose
        GC.SuppressFinalize(this); // tell the GC to not execute the Finalizer
    }

    protected virtual void Dispose(bool disposeManaged)
    {
        if (!disposed)
        {
            if (disposeManaged)
            {
                if (sqlConnection != null)
                {
                    sqlConnection.Dispose();
                }
            }

            unmanagedHandle.Release();

            disposed = true;
        }
    }

    ~ManagedAndUnmanagedObject()
    {
        Dispose(false);
    }
}

IDisposable, Dispose

.NET Framework는 분리 방법이 필요한 유형의 인터페이스를 정의합니다.

public interface IDisposable
{
  void Dispose();
}

Dispose() 는 주로 비 관리 참조 같은 리소스 정리에 사용됩니다. 그러나 관리되는 경우에도 다른 리소스를 강제로 폐기하는 것이 유용 할 수 있습니다. GC가 결국 데이터베이스 연결을 정리하기를 기다리는 대신 자신의 Dispose() 구현에서 완료되었는지 확인할 수 있습니다.

public void Dispose()
{
   if (null != this.CurrentDatabaseConnection)
   {
       this.CurrentDatabaseConnection.Dispose();
       this.CurrentDatabaseConnection = null;
   }
}

관리되지 않는 포인터 또는 win32 리소스와 같은 관리되지 않는 리소스에 직접 액세스해야하는 경우 SafeHandle 에서 상속하는 클래스를 만들고 해당 클래스의 규칙 / 도구를 사용하십시오.

관리 자원이있는 상속 된 클래스에서

IDisposable 을 구현하는 클래스를 만든 다음 관리되는 리소스를 포함하는 클래스를 파생시키는 것이 일반적입니다. 클라이언트가 소유 할 수있는 모든 자원을 정리할 수 있도록 Dispose 메서드를 virtual 키워드로 표시하는 것이 좋습니다.

public class Parent : IDisposable
{
    private ManagedResource parentManagedResource = new ManagedResource();

    public virtual void Dispose()
    {
        if (parentManagedResource != null)
        {
            parentManagedResource.Dispose();
        }
    }
}

public class Child : Parent
{
    private ManagedResource childManagedResource = new ManagedResource();

    public override void Dispose()
    {
        if (childManagedResource != null)
        {
            childManagedResource.Dispose();
        }
        //clean up the parent's resources
        base.Dispose();
    }
}

키워드 사용

객체가 IDisposable 인터페이스를 구현하면 using 구문 내에서 객체를 만들 수 있습니다.

using (var foo = new Foo())
{
    // do foo stuff
} // when it reaches here foo.Dispose() will get called

public class Foo : IDisposable
{
    public void Dispose()
    {
        Console.WriteLine("dispose called");
    }
}

데모보기

using 입니다 syntatic 설탕 A의 try/finally 블록; 위의 사용법은 대략 다음과 같이 번역됩니다.

{
    var foo = new Foo();
    try
    {
        // do foo stuff
    }
    finally
    {
        if (foo != null)
            ((IDisposable)foo).Dispose();
    }
}


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow