2015-04-07 19 views
6

Có rất nhiều ví dụ về Mảng hoặc Danh sách các đối tượng IDisposable được trả về từ các hàm trong .NET. Ví dụ: Process.GetProcesses().Để vứt bỏ() hoặc không vứt bỏ() các phần tử trong một mảng các đối tượng IDisposable?

  • Nếu tôi gọi phương thức đó là trách nhiệm của tôi để Vứt bỏ() tất cả các thành viên của mảng khi tôi lặp qua chúng?
  • Tại sao nó phải là trách nhiệm của tôi vì tôi không bao giờ tạo ra các đối tượng và mảng mà tôi đã đưa ra chỉ là con trỏ đến các đối tượng được tạo bên ngoài mã của tôi.

Tôi luôn nghĩ rằng đó là gánh nặng của người sáng tạo để Vứt bỏ(). Vậy quy tắc thích hợp ở đây là gì?

+0

Không có cách nào để 'Người sáng tạo' vứt bỏ chúng hoặc các bộ phận bên trong các lớp đó vì không có destructor. Họ không có quyền kiểm soát của bạn thiết lập một biến để không có gì để sau đó xử lý có đối tượng hoặc nội dung mà yêu cầu xử lý. – OneFineDay

+0

Chắc chắn, bạn có thể, cho Process.GetProcesses() bạn có thể giữ một mảng nội bộ của tất cả các đối tượng Process() mà bạn đã quay trở lại với người gọi và sau đó kiểm tra định kỳ nếu bạn là người duy nhất có tham chiếu đến đối tượng và nếu có Vứt bỏ() – Denis

+3

@Denis Xác định xem có ai khác có liên quan đến nó không phải là điều bạn thực sự có thể làm không. – Servy

Trả lời

7

Không có quy luật chung. Nó sẽ phụ thuộc vào tình hình và cách thức mà phương thức được đề cập được thiết kế, có hay không "bạn" có trách nhiệm xử lý các đối tượng bạn có quyền truy cập. Đây là nơi tài liệu thường quan trọng để giúp người dùng loại hiểu trách nhiệm của họ.

Tôi luôn luôn nghĩ rằng nó là gánh nặng của người sáng tạo để Dispose()

này không thể là đúng sự thật. Đôi khi trường hợp một đối tượng dùng một lần sẽ tồn tại suốt đời của khối mã tạo ra nó. Trong khi đó, đơn giản nhất là khi người sáng tạo có thể vứt bỏ đối tượng, đôi khi việc họ có thể thực hiện là không thể. Khi trả về một đối tượng dùng một lần từ một phương pháp là không thể tạo mã đối tượng dùng một lần để làm sạch nó, vì tuổi thọ của nó cần là nhỏ hơn so với tuổi thọ của vật thể dùng một lần.

+0

Tôi có thể tạo một đối tượng dùng một lần bằng cách khởi tạo một đối tượng trong phần khai báo khối sử dụng. Một khối sử dụng không chính xác là cái gì sẽ giải quyết vấn đề này? Vòng đời của cuộc gọi phương thức tạo đối tượng dùng một lần nhỏ hơn chính đối tượng thực tế dùng một lần ...? Nếu đây không phải là trường hợp và tôi đang thiếu điểm, tôi có thể thuyết phục bạn thêm một ví dụ (ngay cả một ví dụ) cho câu trả lời của bạn? –

+0

Gosh, tôi không đọc tài liệu kỹ lưỡng cho mọi lớp học mà tôi sử dụng. Bạn chắc chắn không có một số quy tắc? – Denis

+0

@Denis, không có quy tắc nào cho tình huống này. Bạn nên tự mình quyết định. – VMAtm

0

Quy tắc rất đơn giản: nếu bạn nghĩ rằng các chương trình khác sẽ sử dụng số IDisposables của bạn, thì đừng hủy chúng. Nếu không, hãy làm đi.

Ví dụ: GetProcesses() trả về các quy trình khác đang được các chương trình khác sử dụng tiềm năng, do đó, bạn không nên bỏ chúng. Từ phía bên kia, các tệp bạn đã mở sẽ được phát hành cho các quy trình khác trong hệ điều hành, vì vậy bạn nên đóng và vứt bỏ các dòng bao bọc phía trên chúng (ví dụ: bạn nên vứt bỏ hơi nước trả về theo phương pháp File.Open).

Cập nhật:
From MSDN:

  • DO thực hiện các mẫu cơ bản Vứt bỏ trên các loại có chứa trường hợp của các loại dùng một lần. Xem phần Mẫu vứt bỏ cơ bản để biết chi tiết về mẫu cơ bản. Nếu loại chịu trách nhiệm về thời gian tồn tại của các đối tượng dùng một lần khác là , nhà phát triển cũng cần có cách để xử lý trong số đó. Sử dụng phương pháp Vứt bỏ của thùng chứa là cách thuận tiện để thực hiện điều này.
    • DO thực hiện cơ bản Vứt bỏ Pattern và cung cấp một finalizer trên các loại tổ chức nguồn lực cần được giải thoát một cách rõ ràng và không có finalizers.
      Ví dụ, mẫu nên được triển khai trên các kiểu lưu trữ bộ đệm không được quản lý. Phần Loại có thể hoàn thiện thảo luận các nguyên tắc liên quan đến triển khai các finalizers.
    • CONSIDER triển khai Mẫu vứt bỏ cơ bản trên các lớp mà bản thân họ không giữ tài nguyên không được quản lý hoặc các đối tượng dùng một lần nhưng có thể có các loại phụ.
+0

nhưng nếu tôi không tiêu diệt chúng, tôi để tay cầm trôi nổi xung quanh ... Vậy tôi có nên tiêu diệt chúng không? Bạn có nghĩ rằng các đối tượng Process() được trả về được chia sẻ hay không. Tôi đặt cược họ mới được tạo ra cho mọi yêu cầu để Process.GetProcesses() và nếu bạn không vứt bỏ bạn có thể sẽ có một rò rỉ xử lý ... – Denis

+0

Quy trình - không, bạn không nên (nếu bạn không tạo ra chúng) . Hình ảnh hoặc tệp hoặc các nội dung khác như vậy - có, bạn nên làm như vậy. – VMAtm

+0

"Tôi để lại tay cầm trôi nổi xung quanh" - chúng sẽ được hoàn thành vì vậy nó là ok – Vlad

1

Với ngoại lệ tương đối ít (hầu hết các trường hợp có thể được mô tả là phương pháp tối thiểu để xử lý mã không được thiết kế kém), mỗi trường hợp IDisposable nên tại bất kỳ thời điểm cụ thể nào chủ sở hữu được xác định rõ. Trong trường hợp một phương thức trả về một cái gì đó của một loại thực hiện IDisposable, hợp đồng cho phương thức sẽ chỉ rõ liệu phương thức có từ bỏ quyền sở hữu hay không. từ bỏ quyền sở hữu cho người khác), hoặc liệu phương pháp chỉ đơn thuần là trả về một tham chiếu đến một đối tượng được sở hữu bởi một người khác.

Trong mã được viết đúng cách, câu hỏi có hay không một đối tượng cần được xử lý hiếm khi là cuộc gọi phán quyết. Chủ sở hữu của một đối tượng phải đảm bảo rằng nó được xử lý; không ai khác nên vứt bỏ nó. Thỉnh thoảng, có thể cần phải có phương thức chấp nhận tham số cho biết liệu phương thức có nên chuyển quyền sở hữu của một số IDisposable hay không. Ví dụ: nếu mã muốn tạo âm thanh, hãy chuyển âm thanh đó sang phương thức "bắt đầu phát âm thanh" và không bao giờ muốn xử lý lại âm thanh đó, có thể thuận tiện nhất để mã phát âm thanh chấp nhận và vứt bỏ âm thanh khi nó được thực hiện; nếu mã muốn có thể phát âm thanh nhiều lần, tuy nhiên, và sẽ đảm bảo rằng đối tượng âm thanh sẽ vẫn hoạt động miễn là cần thiết, nó sẽ thuận tiện hơn cho mã phát âm để không chiếm quyền sở hữu. Sử dụng các phương pháp riêng biệt có thể theo một số cách được sạch hơn, nhưng sử dụng một tham số có thể hỗ trợ đóng gói.

Nói chung, khi mã trả về danh sách đối tượng triển khai IDisposable, mục đích của mã là xác định các đối tượng mà không truyền đạt bất kỳ quyền sở hữu nào đối với chúng. Trong trường hợp không có quyền sở hữu, mã nhận danh sách như vậy phải không phải gọi Dispose trên đó.

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