2011-10-18 54 views
11

Tôi đã đọc rất nhiều về finalizer và IDisposable trong C#. Khi tôi cuối cùng đã trở nên rõ ràng từ sự nhầm lẫn quái dị này trên finalizer và IDisposable, đột nhiên, ra khỏi hư không, có điều SafeHandle này. Niềm tin của tôi hoàn toàn bị lung lay trở lại. Tôi phải sử dụng cái gì?C# sử dụng IDisposable hoặc SafeHandle?

+2

Sử dụng cho * what *, chính xác? –

+0

Sử dụng cho những gì, chính xác. Tôi không biết tôi nên sử dụng cái nào trong tình huống hiện tại vì có 2 cấu trúc tương tự như vậy. –

+1

@HansPassant Khi đọc bài đăng MSDN về cách triển khai IDisposable, Microsoft trình bày hai tùy chọn cách thực hiện điều đó. Một người đang triển khai trình hoàn thiện và người được khuyến nghị đang sử dụng SafeHandle. Nó thực sự là một chút khó hiểu và gây nhầm lẫn, vì vậy tôi có thể hiểu câu hỏi của OP rất tốt. URL: http://msdn.microsoft.com/en-us/en-en/library/fs2xkftw%28v=vs.110%29.aspx Trang web làm cho âm thanh rất chung chung, vì vậy lần đầu tiên tôi thử tải Các đối tượng bút được xử lý đúng cách cũng là với SafeHandle, vốn không hiệu quả lắm. – Tom

Trả lời

15

SafeHandle chỉ hữu ích khi xử lý các cuộc gọi Interop Interop. Trong Win32, hầu hết mọi thứ được đại diện bởi "xử lý". Điều này bao gồm Windows, Mutexes, vv Vì vậy, NET SafeHandle sử dụng mẫu dùng một lần để đảm bảo xử lý Win32 được đóng đúng cách.

Vì vậy, nếu bạn đang sử dụng các cuộc gọi Interop Inter32 và nhận lại các điều khiển Win32, hãy sử dụng SafeHandle. Đối với các đối tượng của riêng bạn, bạn sẽ gắn bó với IDisposable và finalizer.

+0

Nhưng toàn bộ điểm của [IDisposable] (https://msdn.microsoft.com/en-us/library/system.idisposable (v = vs.110) .aspx), là để giải phóng * tài nguyên không được quản lý *, không nó? "đối tượng của riêng bạn" không rõ ràng, vì đối tượng có thể đại diện cho cả đối tượng được quản lý * và * không được quản lý, và kể từ đó, bạn là nhà phát triển, có thể phát triển cả mã bị cấm và không được quản lý và gọi mã không được quản lý từ mã được quản lý của bạn cũng bị mờ. –

+0

@zespri - Nếu bạn quyết định triển khai IDisposable, điều đó ngụ ý rằng bạn đang duy trì lớp/đối tượng (nghĩa là đó là của bạn). Nếu đó là một đối tượng từ thư viện của bên thứ ba, thì bạn không thể triển khai IDisposable (nghĩa là nó không phải của bạn). Tôi không đề cập đến những gì cần được xử lý, cũng như bạn sẽ không triển khai IDisposable trong mã không được quản lý. – CodeNaked

+0

Nhưng nếu đó là một đối tượng từ thư viện của bên thứ ba (được quản lý), bạn cũng không thể thực hiện 'SafeHandle'?Chỉ vì bạn có khả năng không có bất kỳ tầm nhìn trực tiếp nào của tay cầm ở nơi đầu tiên? Xin lỗi, không phải là chiến đấu, chỉ cố gắng hiểu ý bạn là gì. –

5

Bạn có thể/nên sử dụng SafeHandle cho bất kỳ tài nguyên không được quản lý nào có thể được biểu diễn dưới dạng IntPtr, tức là xử lý Win32, bộ nhớ được cấp bởi mã không được quản lý và cứ thế. Khi SafeHandle không phù hợp, nhưng bạn vẫn cần xử lý các tài nguyên không được quản lý, hãy cân nhắc tạo lớp giống như SafeHandle của bạn kế thừa từ CriticalFinalizerObject.

Trong tất cả các trường hợp khác (tức là xử lý tài nguyên được quản lý), hãy triển khai IDisposable. Trong hầu hết các trường hợp, bạn sẽ không cần finalizer, hầu hết các tài nguyên được quản lý sẽ không có sẵn khi finalizer được gọi, vì vậy sẽ không có gì để làm ở đó.

2

Trong hầu hết các trường hợp, lời khuyên của tôi là giả vờ rằng không có thứ gì như finalizer, nhưng chắc chắn 100% rằng bất kỳ đối tượng IDisposable nào được tạo sẽ bị hủy. Thậm chí nếu finalizers được viết 100% tối ưu, mã phân phối một nửa đối tượng của nó đúng và cho phép finalizers xử lý một nửa khác sẽ không được tốt như mã mà disposes của tất cả các đối tượng của nó đúng và không sử dụng finalizers. Mặc dù tác động hiệu suất từ ​​finalizers mà không bao giờ chạy thường không quá khủng khiếp, finalizers rất khó để viết chính xác, họ có thể gây ra Heisenbugs nếu mã của họ hoặc mã tiêu thụ chúng không được viết hoàn hảo. Hơn nữa, việc thực hiện thành công finalizers thường sẽ yêu cầu tạo ra một hoặc nhiều WeakHandles mà chỉ có mục đích là để hỗ trợ hoàn thiện.

Có lẽ mạng lưới an toàn hoàn thành đáng giá, nhưng chi phí có thể đáng kể và mạng lưới an toàn không đáng tin cậy như người ta có thể muốn.

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