2010-01-13 22 views
8

Tôi đã lớp sauSử dụng IDisposable để hủy đăng ký sự kiện-- Tôi có cần đặt những thứ khác vào mục đích không?

public class Presenter: IDisposable 
{ 
    public IView View 
    {get;private set;} 

    //snip other object reference, all managed 
    public Presenter(IView view) 
    { 
    View=view; 
    View.MouseUp += MouseUpEvent; 
    } 

    public void MouseUpEvent() 
    { 
    //do whatever you want to do on mouse up 
    } 

    public void Dispose() 
    { 
    View.MouseUp -= MouseUpEvent; 
    // no more manual disposing 
    } 
} 

Câu hỏi đặt ra bây giờ là, tôi thực hiện Dispose() phương pháp chính xác? Hoặc tôi có cần phải xử lý thủ công tất cả các đối tượng được quản lý khác chỉ vì tôi đã xác định rõ ràng Dispose()?

Tôi cho rằng GC đủ thông minh để tự xử lý (trừ đăng ký sự kiện) ngay cả khi tôi không thực hiện thủ công. Tôi có đúng không?

Trả lời

8

Nếu bạn chọn lựa đăng ký trong hàm tạo, điều này có vẻ hợp lý. Tôi sẽ lặp lại ý kiến ​​của Josh rằng nó có thể không phải là cách tiếp cận tốt nhất. Mặt khác, nó có thể là cách đơn giản nhất để đạt được mục tiêu của bạn, điều luôn luôn là một điều tốt. Tôi sẽ không giả vờ là một chuyên gia về các mẫu giao diện người dùng: đã nêu lên mối quan tâm, tôi sẽ giả định rằng đây là cách bạn muốn làm việc và tự giải quyết vấn đề :)

Cá nhân tôi tìm thấy quy định của Josh pattern quá phức tạp cho các tình huống đơn giản - cách tiếp cận của bạn là tốt, chỉ với một thay đổi: làm cho lớp của bạn được niêm phong. Nếu bạn không muốn đóng dấu lớp học, bạn nên chọn tùy chọn Dispose(bool) (nhưng không có trình kết thúc) vì lớp con cũng có thể cần phải vứt bỏ mọi thứ và có thể cần trình hoàn tất. Nếu không có khả năng của một loại có nguồn gốc, cuộc sống là đơn giản (như nó thường xuyên như vậy).

Bạn không cần làm bất kỳ điều gì với các thành viên khác chỉ vì bây giờ bạn thực hiện IDiposable vì một lý do đó.

Vì vậy, bạn có cần tìm thêm bất kỳ từ lớp học này không?


tôi hiểu rằng đây là mô hình chuẩn được khuyến cáo, mặc dù tôi muốn khuyên bạn nên đọc những lời khuyên của Joe Duffy et al cho dù biết thêm chi tiết - nó có thể tất cả được rất phức tạp.

+0

Tôi không nghĩ mình cần nó. Tôi chấp nhận câu trả lời của bạn về Einstein bởi vì tôi thấy bạn dễ hiểu hơn (không phải mọi sinh tử đều có thể hiểu Einstein :)). – Graviton

+0

Nếu không có chủ đề, tôi hiểu rằng nếu lớp đó không bị niêm phong, bạn nên * có một finalizer (như trường hợp với Component) ngay cả khi bạn không nắm giữ tài nguyên không được quản lý bởi vì lớp con có thể và không nên phải biết liệu lớp cơ sở có chịu trách nhiệm gọi Dispose (bool) tại finalization hay không. Nhưng như tôi đã nói tôi đang rời khỏi chủ đề. – Josh

+0

@Josh: Tôi tin rằng nếu bạn cần một finalizer trong lớp của bạn, bạn nên thực hiện một và gọi 'Dispose (false)'. 'Dispose' phải được gọi nhiều lần. Điều này là tốt hơn so với việc tải các lớp với các finalizers không cần thiết. Finalizers nên hiếm trong những ngày này (với 'SafeHandle' et al) nhưng họ có một chi phí thực sự thực sự liên kết với họ. –

5

Cá nhân, tôi sẽ tránh hooking/không tìm kiếm sự kiện trong hàm tạo và hủy bỏ. Thay vào đó tôi sẽ thêm mã vào View get/set accessors và thêm chúng vào đó. Nhưng nếu thuyết trình được xử lý trong khi một View được đính kèm, tôi sẽ không bận tâm cố gắng để làm sạch mà lên. Bạn có thể tách Chế độ xem khỏi trình bày một cách rõ ràng nếu bạn cần tách biệt rõ ràng.

Có nói rằng, đây là những gì tôi biết về IDisposable.

Cách tiếp cận được đề xuất cho implementing IDisposable là có phương thức Vứt bỏ (bool) được bảo vệ nơi bạn thực hiện hành động. Lý do là, bạn muốn phân biệt giữa việc xử lý rõ ràng và xử lý gây ra bởi việc hoàn thành (thu gom rác thải.)

Khi bạn đang bị xử lý vì một lệnh Dispose() rõ ràng, bạn có thể chạm vào các đối tượng được quản lý và bạn dự kiến ​​sẽ vứt bỏ bất cứ thứ gì bạn đã tạo mà cũng cần xử lý. Vì vậy, bạn làm điều này chỉ khi vứt bỏ = true.

Nhưng nếu ai đó (bạn) quên gọi Dispose và finalizer được gọi, bạn đang bị xử lý sau khi thu gom rác thải (disposing = false) và bạn không muốn chạm vào bất kỳ đối tượng được quản lý nào vì chúng có thể đã được hoàn tất . Điều duy nhất bạn cần giải phóng trong trường hợp này là các tài nguyên không được quản lý như Win32 và những thứ như vậy.

Cuối cùng, khi Dispose() được gọi rõ ràng, bạn sẽ nhận thấy tôi được gọi là GC.SupressFinalize (đây) là gợi ý hiệu suất cho bộ thu gom rác. Nó cho phép nó biết rằng đối tượng không cần phải được hoàn thành khi nó được thu thập. Quyết toán không phải là rẻ.

class MyObject : IDisposable { 

    ~MyObject() { 
     Dispose(false); 
    } 

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

    protected virtual void Dispose(bool disposing) { 
     if (disposing) { 
      // dispose of managed resources 
     } 
     // dispose of unmanaged resources 
    } 

} 
+3

Bạn không muốn thêm trình kết thúc ('~ MyObject() {Dispose (false);}') trừ khi lớp của bạn chứa tài nguyên không được quản lý. Trong trường hợp đó, nó thích hợp hơn để bọc các tài nguyên không được quản lý trong một 'SafeHandle'. Nói chung, các đối tượng được thiết kế tốt đang triển khai 'IDisposable' sẽ xuất phát từ' CriticalFinalizerObject' hoặc sẽ không có trình hoàn thiện. –

+0

Điểm rất tốt về trình hoàn thiện. – Josh

Các vấn đề liên quan