2009-03-05 62 views
17

Nếu .NET có bộ sưu tập rác thì tại sao bạn phải gọi IDisposable?IDisposable là gì?

+2

Có nhiều câu trả lời hiện có cho câu hỏi này nếu bạn đặt IDisposable vào hộp tìm kiếm. –

Trả lời

46

Bộ sưu tập rác là dành cho bộ nhớ. Bạn cần phải loại bỏ các tài nguyên không nhớ - xử lý tệp, ổ cắm, xử lý GDI +, kết nối cơ sở dữ liệu v.v. Đó thường là điều làm nền tảng cho loại IDisposable, mặc dù xử lý thực tế có thể là một chuỗi dài tham chiếu. Ví dụ: bạn có thể Dispose một số XmlWriter để phân phối một số StreamWriter mà nó có tham chiếu đến, trong đó phân bổ FileStream có tham chiếu đến, bản phát hành tệp sẽ tự xử lý.

5

Vì các đối tượng đôi khi giữ tài nguyên bên cạnh bộ nhớ. GC giải phóng bộ nhớ; IDisposable là để bạn có thể phát hành bất kỳ thứ gì khác.

1

vì bạn muốn kiểm soát thời điểm các tài nguyên được giữ bởi đối tượng của bạn sẽ bị xóa.

Xem, GC hoạt động, nhưng nó sẽ làm như vậy khi nó cảm thấy như nó, và thậm chí sau đó, finalisers bạn thêm vào đối tượng của bạn sẽ được gọi chỉ sau 2 bộ sưu tập GC. Đôi khi, bạn muốn làm sạch những đồ vật đó ngay lập tức.

Đây là thời điểm sử dụng IDisposable. Bằng cách gọi Dispose() một cách rõ ràng (hoặc sử dụng đường cú pháp của khối sử dụng), bạn có thể truy cập đối tượng của mình để tự dọn dẹp theo cách tiêu chuẩn (nghĩa là bạn có thể đã thực hiện cuộc gọi dọn dẹp của riêng mình).

Tài nguyên mẫu bạn muốn xóa ngay lập tức là: xử lý cơ sở dữ liệu, xử lý tệp, xử lý mạng.

8

Mở rộng một chút về ý kiến ​​khác:

Các phương thức Dispose() nên được gọi là trên tất cả các đối tượng có tham chiếu đến các nguồn tài nguyên chưa được quản lý. Ví dụ như vậy sẽ bao gồm các luồng tập tin, kết nối cơ sở dữ liệu vv. Một quy tắc cơ bản hoạt động phần lớn thời gian là: "nếu đối tượng .NET thực hiện IDisposable thì bạn nên gọi Dispose() khi bạn đã hoàn thành với đối tượng. Tuy nhiên, một số thứ khác cần lưu ý:.

  • gọi Vứt bỏ không cung cấp cho bạn kiểm soát khi các đối tượng đang thực sự bị phá hủy và bộ nhớ phát hành GC xử lý đó đối với chúng tôi và làm nó tốt hơn so với chúng ta có thể
  • . Vứt bỏ dọn dẹp tất cả các tài nguyên bản địa, tất cả các con đường xuống ngăn xếp các lớp cơ sở như Jon chỉ ra, sau đó nó gọi SuppressFinalize() để chỉ ra rằng đối tượng đã sẵn sàng để được khai hoang và không cần làm thêm nữa. Lần chạy tiếp theo của GC sẽ làm sạch nó.
  • Nếu Dispose không được gọi, GC sẽ tìm đối tượng cần được dọn sạch, nhưng Finalize phải được gọi trước, để đảm bảo tài nguyên được giải phóng, yêu cầu Finalize đó được xếp hàng và GC di chuyển, thiếu một cuộc gọi để vứt bỏ lực lượng thêm GC để chạy trước khi đối tượng có thể được làm sạch. Điều này làm cho đối tượng được quảng cáo đến "thế hệ" tiếp theo của GC. Điều này có vẻ không phải là một vấn đề lớn, nhưng trong một ứng dụng bộ nhớ bị áp lực, việc thúc đẩy các đối tượng lên đến các thế hệ GC cao hơn có thể đẩy một ứng dụng bộ nhớ cao lên tường để trở thành một ứng dụng ngoài bộ nhớ.
  • Không triển khai IDisposable trong các đối tượng của riêng bạn trừ khi bạn thực sự cần. Triển khai kém hoặc triển khai không cần thiết thực sự có thể làm mọi thứ tồi tệ hơn thay vì tốt hơn.Một số hướng dẫn tốt có thể được tìm thấy ở đây:

    Implementing a Dispose Method

    Or read that whole section of MSDN on Garbage Collection

+0

Re: "Không thực hiện IDisposable ... trừ khi bạn hoàn toàn cần phải" -just cẩn thận khi xác định giao diện -if có bất kỳ cơ hội rằng một thực hiện giao diện có thể yêu cầu xử lý sau đó giao diện nên được idisposable từ đầu. Nếu không, tất cả các khách hàng sẽ cần tái cấu trúc. – morechilli

+0

+1 để có câu trả lời tốt và kỹ lưỡng hơn. Tôi nghi ngờ rằng các cảnh báo về việc không thực hiện một cái gì đó, trừ khi bạn phải được hướng nhiều hơn tại 'Finalize()' hơn 'Dispose()' mặc dù. –

+0

Mục đích của 'IDisposable' là cung cấp một phương tiện tiêu chuẩn cho phép các đối tượng biết khi nào các dịch vụ của họ không còn cần thiết nữa. Điều này lần lượt cho phép họ thông báo cho các đối tượng khác có dịch vụ mà họ đã sử dụng mà các dịch vụ của các đối tượng khác không còn cần thiết nữa. Các đối tượng quan tâm khi dịch vụ của họ không còn cần phải thực hiện 'IDisposable'. Các đối tượng sở hữu các đối tượng khác quan tâm khi chúng không còn cần thiết nên tương tự như vậy thực hiện 'IDisposable', vì vậy chúng có thể chuyển tiếp thông báo" không còn cần thiết "cho các đối tượng bên trong đó nữa. – supercat

0

Giao diện IDisposable thường được mô tả về mặt tài nguyên, nhưng hầu hết các mô tả như vậy không thực sự xem xét "tài nguyên" thực sự có ý nghĩa gì.

Một số đối tượng cần phải yêu cầu các bên ngoài thực hiện điều gì đó thay mặt họ, gây tổn hại cho các thực thể khác, cho đến khi có thông báo mới. Ví dụ, một đối tượng bao gồm một luồng tập tin có thể cần phải yêu cầu một hệ thống tệp (có thể ở bất kỳ đâu trong vũ trụ được kết nối) để cấp quyền truy cập độc quyền vào một tệp. Trong nhiều trường hợp, nhu cầu của đối tượng cho thực thể bên ngoài sẽ được gắn với nhu cầu của mã bên ngoài đối với đối tượng. Một khi mã khách hàng đã làm tất cả mọi thứ nó sẽ làm với đối tượng luồng tập tin nói trên, ví dụ, đối tượng đó sẽ không còn cần phải có quyền truy cập độc quyền (hoặc bất kỳ truy cập nào cho vấn đề đó) vào tệp được liên kết của nó.

Nói chung, đối tượng X yêu cầu một thực thể làm điều gì đó cho đến khi có thông báo tiếp theo phải chịu trách nhiệm gửi thông báo đó, nhưng không thể gửi thông báo đó miễn là khách hàng của X có thể cần các dịch vụ của X. Mục đích của IDisposable là cung cấp một cách thống nhất để cho phép các đối tượng biết rằng các dịch vụ của họ sẽ không còn cần thiết nữa, để họ có thể thông báo cho các thực thể (nếu có) đã hành động thay mặt cho họ các dịch vụ của họ không còn cần thiết nữa. Mã gọi IDisposable không cần biết hoặc không quan tâm đến những dịch vụ (nếu có) mà đối tượng yêu cầu từ bên ngoài, vì IDisposable chỉ mời một đối tượng thực hiện nghĩa vụ (nếu có) cho các thực thể bên ngoài.

Để đặt mọi thứ về "tài nguyên", một đối tượng mua lại tài nguyên khi yêu cầu một thực thể bên ngoài làm điều gì đó thay mặt cho nó (thông thường, không nhất thiết, cấp quyền sử dụng độc quyền) cho đến khi có thông báo mới một nguồn lực khi nó nói rằng thực thể bên ngoài dịch vụ của nó không còn cần thiết nữa. Mã mà mua lại một nguồn tài nguyên không đạt được một "điều" nhiều như nó phải chịu một nghĩa vụ; việc phát hành một tài nguyên không từ bỏ một "điều", mà thay vào đó thực hiện nghĩa vụ.

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