2011-08-06 27 views
34

thể trùng lặp:
Will the Garbage Collector call IDisposable.Dispose for me?IDisposable.Dispose() có được gọi tự động không?

Tôi có một lớp trong đó có một số tài nguyên không được quản lý. Lớp của tôi triển khai giao diện IDisposable và giải phóng tài nguyên không được quản lý theo phương thức Dispose(). Tôi có phải gọi phương thức Dispose() hoặc nó sẽ tự động được gọi bằng cách nào đó không? Garbage Collector sẽ gọi nó?

Trả lời

44

Dispose() sẽ không được gọi tự động. Nếu có finalizer, nó sẽ được gọi tự động. Việc triển khai IDisposable cung cấp cách để người dùng của lớp của bạn sớm phát hành tài nguyên, thay vì đợi cho người thu gom rác.

Cách thích hợp hơn cho khách hàng là sử dụng câu lệnh using xử lý cuộc gọi tự động Dispose() ngay cả khi có ngoại lệ.

Một thực hiện đúng IDisposable là:

class MyClass : IDisposable 
{ 
    private bool disposed = false; 

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

    protected virtual void Dispose(bool disposing) 
    { 
    if(!disposed) 
    { 
     if(disposing) 
     { 
     // Manual release of managed resources. 
     } 
     // Release unmanaged resources. 
     disposed = true; 
    } 
    } 

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

Nếu người dùng của lớp gọi Dispose() dọn dẹp diễn ra trực tiếp. Nếu đối tượng bị thu thập bởi bộ thu gom rác, nó sẽ gọi Dispose(false) để thực hiện việc dọn dẹp. Xin lưu ý rằng khi được gọi từ trình hoàn thiện (phương thức ~MyClass), các tham chiếu được quản lý có thể không hợp lệ, vì vậy chỉ có thể phát hành các tài nguyên không được quản lý.

3

Bạn sẽ phải gọi phương pháp này bằng tay, có lẽ trong một cấu trúc giống như

using(var myclass = new MyClass()) 
{ 
    // do something with myclass 
} 

// now 'myclass'is Disposed 
5

Nếu bạn nhanh chóng đối tượng của bạn trong một tuyên bố using, Dispose() được gọi cho bạn khi mã thoát khối using

using(var myObject = new MyDisposableObject()) 
{ 
    blah(); 
} // Dispose() is called here (or whenever the code exits the block) 

Nếu bạn không sử dụng using, thì đó là tùy thuộc vào bạn (mã gọi) để xử lý đối tượng của bạn bằng cách explicitely gọi Dispose().

Ngoài ra, bạn (người triển khai MyObject) có thể thêm hỗ trợ cho trình hoàn thiện trong trường hợp người gọi của bạn không gọi Dispose(). Thông tin thêm here.

6

Để đảm bảo tài nguyên được xử lý chính xác, bạn cần phải triển khai cả hai IDisposable và gọi Dispose trong trình phá hủy (trình kết thúc).

class Foo : IDisposable 
{ 
    private bool m_disposed = false; 

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

    ~Foo() 
    { 
     Dispose(false); 
    } 

    protected void Dispose(bool disposing) 
    { 
     if (!m_disposed) 
     { 
      if (disposing) 
      { 
       //release managed resources 
      } 
      //release unmanaged resources 

      m_disposed = true; 
     } 
    } 
} 
Các vấn đề liên quan