[C#] IDisposable을 올바르게 구현

내 수업에서는 다음과 같이 IDisposable을 구현합니다.

public class User : IDisposable
{
    public int id { get; protected set; }
    public string name { get; protected set; }
    public string pass { get; protected set; }

    public User(int UserID)
    {
        id = UserID;
    }
    public User(string Username, string Password)
    {
        name = Username;
        pass = Password;
    }

    // Other functions go here...

    public void Dispose()
    {
        // Clear all property values that maybe have been set
        // when the class was instantiated
        id = 0;
        name = String.Empty;
        pass = String.Empty;
    }
}

VS2012에서 코드 분석에 IDisposable을 올바르게 구현한다고 나와 있지만 여기서 내가 잘못한 일이 확실하지 않습니다.
정확한 텍스트는 다음과 같습니다.

CA1063 구현 IDisposable ‘User’에서 무시할 수있는 Dispose (bool) 구현을 제공하거나 유형을 봉인 된 것으로 표시하십시오. Dispose (false)를 호출하면 기본 리소스 만 정리해야합니다. Dispose (true)를 호출하면 관리 자원과 기본 자원을 모두 정리해야합니다. stman User.cs 10

참조 : CA1063 : IDisposable을 올바르게 구현

이 페이지를 읽었지만 여기에서 수행해야 할 작업을 실제로 이해하지 못합니다.

누군가가 더 많은 라멘 용어로 문제가 무엇인지 또는 IDisposable을 어떻게 구현해야하는지 설명 할 수 있다면 정말 도움이 될 것입니다!



답변

게시 한 코드에서 처리해야 할 내용이 없지만 올바른 구현입니다. 다음과 같은 경우에만 구현 IDisposable하면됩니다.

  1. 관리되지 않는 리소스가 있습니다
  2. 당신은 스스로 처분 할 수있는 것들을 언급하고 있습니다.

게시 한 코드의 어떤 것도 폐기 할 필요가 없습니다.

public class User : IDisposable
{
    public int id { get; protected set; }
    public string name { get; protected set; }
    public string pass { get; protected set; }

    public User(int userID)
    {
        id = userID;
    }
    public User(string Username, string Password)
    {
        name = Username;
        pass = Password;
    }

    // Other functions go here...

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

    protected virtual void Dispose(bool disposing)
    {
        if (disposing) 
        {
            // free managed resources
        }
        // free native resources if there are any.
    }
}


답변

우선, 당신은 “정리”할 필요가 없습니다 string들과 int의 – 그들은 가비지 컬렉터에 의해 자동으로 처리됩니다. 정리할 필요가있는 유일한 것은 Dispose관리되지 않는 리소스 또는 구현 된 관리 대상입니다 IDisposable.

그러나 이것이 단지 학습 연습이라고 가정 할 때 권장 되는 구현 방법 IDisposable은 “안전 캐치”를 추가하여 모든 자원이 두 번 폐기되지 않도록하는 것입니다.

public void Dispose()
{
    Dispose(true);

    // Use SupressFinalize in case a subclass 
    // of this type implements a finalizer.
    GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
    if (!_disposed)
    {
        if (disposing)
        {
            // Clear all property values that maybe have been set
            // when the class was instantiated
            id = 0;
            name = String.Empty;
            pass = String.Empty;
        }

        // Indicate that the instance has been disposed.
        _disposed = true;
    }
}


답변

다음 예제는 IDisposable인터페이스 를 구현하는 일반적인 모범 사례를 보여줍니다 . 참고

수업에 관리되지 않는 리소스가있는 경우에만 소멸자 (완료 자)가 필요합니다. 소멸자를 추가하면 Dispose에서 Finalization을 억제해야합니다 . 그렇지 않으면 두 가비지주기 동안 객체가 메모리에 상주하게됩니다 (참고 : Finalization 작동 방식 읽기 ). 아래 예제는 위의 내용을 자세히 설명합니다.

public class DisposeExample
{
    // A base class that implements IDisposable. 
    // By implementing IDisposable, you are announcing that 
    // instances of this type allocate scarce resources. 
    public class MyResource: IDisposable
    {
        // Pointer to an external unmanaged resource. 
        private IntPtr handle;
        // Other managed resource this class uses. 
        private Component component = new Component();
        // Track whether Dispose has been called. 
        private bool disposed = false;

        // The class constructor. 
        public MyResource(IntPtr handle)
        {
            this.handle = handle;
        }

        // Implement IDisposable. 
        // Do not make this method virtual. 
        // A derived class should not be able to override this method. 
        public void Dispose()
        {
            Dispose(true);
            // This object will be cleaned up by the Dispose method. 
            // Therefore, you should call GC.SupressFinalize to 
            // take this object off the finalization queue 
            // and prevent finalization code for this object 
            // from executing a second time.
            GC.SuppressFinalize(this);
        }

        // Dispose(bool disposing) executes in two distinct scenarios. 
        // If disposing equals true, the method has been called directly 
        // or indirectly by a user's code. Managed and unmanaged resources 
        // can be disposed. 
        // If disposing equals false, the method has been called by the 
        // runtime from inside the finalizer and you should not reference 
        // other objects. Only unmanaged resources can be disposed. 
        protected virtual void Dispose(bool disposing)
        {
            // Check to see if Dispose has already been called. 
            if(!this.disposed)
            {
                // If disposing equals true, dispose all managed 
                // and unmanaged resources. 
                if(disposing)
                {
                    // Dispose managed resources.
                    component.Dispose();
                }

                // Call the appropriate methods to clean up 
                // unmanaged resources here. 
                // If disposing is false, 
                // only the following code is executed.
                CloseHandle(handle);
                handle = IntPtr.Zero;

                // Note disposing has been done.
                disposed = true;

            }
        }

        // Use interop to call the method necessary 
        // to clean up the unmanaged resource.
        [System.Runtime.InteropServices.DllImport("Kernel32")]
        private extern static Boolean CloseHandle(IntPtr handle);

        // Use C# destructor syntax for finalization code. 
        // This destructor will run only if the Dispose method 
        // does not get called. 
        // It gives your base class the opportunity to finalize. 
        // Do not provide destructors in types derived from this class.
        ~MyResource()
        {
            // Do not re-create Dispose clean-up code here. 
            // Calling Dispose(false) is optimal in terms of 
            // readability and maintainability.
            Dispose(false);
        }
    }
    public static void Main()
    {
        // Insert code here to create 
        // and use the MyResource object.
    }
}


답변

IDisposable가비지 콜렉터가 자동으로 정리하지 않는 관리되지 않는 자원 을 정리할 수있는 수단을 제공하기 위해 존재합니다 .

“정리”하는 모든 자원은 관리 자원이며, 따라서 귀하의 Dispose방법은 아무것도 달성하지 못합니다. 수업이 전혀 구현되어서는 안됩니다 IDisposable. 가비지 콜렉터는 해당 필드를 모두 잘 처리합니다.


답변

다음 과 같이 일회용 패턴 을 사용해야합니다 .

private bool _disposed = false;

protected virtual void Dispose(bool disposing)
{
    if (!_disposed)
    {
        if (disposing)
        {
            // Dispose any managed objects
            // ...
        }

        // Now disposed of any unmanaged objects
        // ...

        _disposed = true;
    }
}

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

// Destructor
~YourClassName()
{
    Dispose(false);
}


답변

클래스 관리 되지 않는 리소스 (파일, 데이터베이스 연결 등)를 얻지 않으므로User 클래스 를 수행 할 필요 가 없습니다 . 일반적으로 클래스는 하나 이상의 필드 또는 속성 이있는 것처럼 표시
합니다. 구현할 때 Microsoft의 일반적인 체계에 따라 더 잘 작성하십시오.IDisposableIDisposableIDisposableIDisposable

public class User: IDisposable {
  ...
  protected virtual void Dispose(Boolean disposing) {
    if (disposing) {
      // There's no need to set zero empty values to fields 
      // id = 0;
      // name = String.Empty;
      // pass = String.Empty;

      //TODO: free your true resources here (usually IDisposable fields)
    }
  }

  public void Dispose() {
    Dispose(true);

    GC.SuppressFinalize(this);
  }
}


답변

결정적 (확인 된) 가비지 수집을 원할 때마다 Idisposable을 구현합니다.

class Users : IDisposable
    {
        ~Users()
        {
            Dispose(false);
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
            // This method will remove current object from garbage collector's queue 
            // and stop calling finilize method twice 
        }

        public void Dispose(bool disposer)
        {
            if (disposer)
            {
                // dispose the managed objects
            }
            // dispose the unmanaged objects
        }
    }

Users 클래스를 만들고 사용할 때 “pose”블록을 사용하여 dispose 메서드를 명시 적으로 호출하지 않도록합니다.

using (Users _user = new Users())
            {
                // do user related work
            }

작성된 using 블록의 끝 users 객체는 dispose 메서드의 암시 적 호출에 의해 처리됩니다.