2009-03-07 26 views

Trả lời

9

Luôn luôn có một finalizer trong IL - System.Object.Finalize() tồn tại trong mỗi lớp, vì vậy nếu bạn thực hiện một lớp tùy chỉnh, nó có một finalizer bạn muốn ngăn chặn. Điều đó đang được nói, không phải tất cả các đối tượng được đưa vào hàng đợi cuối cùng, do đó, bạn chỉ cần kỹ thuật cần phải triệt tiêu hoàn thiện nếu bạn thực hiện finalizer của riêng bạn.

Nếu bạn đang triển khai IDisposable để bọc tài nguyên không được quản lý, bạn nên bao gồm trình hoàn thiện và bạn nên ngăn điều này chạy vì lý do bạn đang thực hiện dọn dẹp khi gọi Dispose.

+0

Đúng. Ngoài ra, bạn nên có một finalizer gọi Dispose(). – configurator

+0

True- Object.Finalize là một op không, nhưng nếu bạn đang thực hiện IDisposable, bạn đang nói rằng bạn có tài nguyên để giải phóng. Từ MSDN, điều đó có nghĩa là bạn nên luôn có trình hoàn thiện để giải phóng chúng, vì vậy chúng được xử lý chính xác. Điều này có nghĩa là có Finalize gọi Dispose, và Dispose suppress finalization –

+4

@configurator Bạn chỉ nên có một finalizer nếu bạn trực tiếp sở hữu tài nguyên không được quản lý (chẳng hạn như xử lý). Nếu bạn chỉ sở hữu chúng một cách gián tiếp, ví dụ: một tham chiếu đến một FileStream, tại sao bạn nên viết bất cứ điều gì nhiều hơn IDisposable.Dispose() {if (fs! = null) {fs.Dispose(); fs = null; }}? IMO, StyleCop là một công cụ khủng khiếp buộc một LOT của văn bản vô dụng được viết và duy trì, và cho biết thêm không có giá trị kinh doanh trong trở lại. –

2

Tất cả các đối tượng đều có phương thức finalizer, ngay cả khi bạn chưa thực hiện một phương thức nào bằng cách sử dụng một trình phá hủy C# (vốn không thực sự được đảm bảo để gọi bởi GC). Nó chỉ là thực hành tốt để ngăn chặn các cuộc gọi nếu bạn đã thực hiện IDisposable bởi vì điều đó có nghĩa là bạn đã quyết định thực hiện quyết toán explictly.

devx article

+0

Bạn có thể giải thích "không được đảm bảo để được GC gọi" không? –

+0

Trong khi chấm dứt chương trình, một số đối tượng có thể không có cơ hội để chạy finalizers của họ nếu dọn dẹp mất quá nhiều thời gian. Đó có thể là những gì anh ta đang đề cập đến. –

+0

Vâng, đó là những gì tôi đã đề cập đến. – x0n

2

Tôi không thấy cần phải gọi SuppressFinalize() nếu không có trình xác nhận cuối cùng nào được xác định. Nếu bạn muốn được bảo vệ thì nó có thể là tốt để có một finalizer cũng như Dispose(), vì vậy bạn không cần phải dựa vào khách hàng để luôn gọi Dispose(). Sau đó, bạn sẽ không bị rò rỉ tài nguyên khi họ quên.

+0

Nếu một đối tượng là "chịu trách nhiệm" cho khác, IDisposable, các đối tượng nhưng không có tài nguyên không được quản lý bởi chính nó thì nó cần Dispose nhưng không có Finalizer. –

20

Không cần phải gọi GC.SuppressFinalize(this) trong Vứt bỏ, trừ khi:

  • Bạn là lớp cơ sở mà thực hiện phương pháp Vứt bỏ ảo dành cho trọng (một lần nữa, nó có thể không là trách nhiệm của bạn ngay cả ở đây, nhưng bạn có thể muốn để làm điều đó trong trường hợp đó)
  • Bạn có trình tự quyết toán. Về mặt kỹ thuật, mọi lớp trong .NET đều có trình hoàn thiện, nhưng nếu trình kết xuất duy nhất là một trong số Object thì đối tượng đó không được xem là cần hoàn thiện và không được đưa vào danh sách hoàn chỉnh khi GC

I giả sử bạn không có bất kỳ trường hợp nào ở trên, bạn có thể bỏ qua thông báo đó một cách an toàn.

+1

Khi nào một lớp dẫn xuất * EVER * thêm trình hoàn thiện vào một lớp cơ sở không tầm thường? Tại sao thêm mã để cho phép một lớp dẫn xuất để làm một cái gì đó nó không bao giờ nên làm gì? – supercat

+0

@supercat Nếu một lớp dẫn xuất sở hữu bất kỳ tài nguyên không được quản lý nào, nó sẽ có trình hoàn thiện để đảm bảo chúng được giải phóng. Nếu đối tượng luôn luôn được sử dụng đúng (với một lệnh thử cuối cùng hoặc tương đương, một câu lệnh sử dụng) Dispose sẽ làm sạch và ngăn chặn finalizer, nhưng finalizer đảm bảo các tài nguyên không được quản lý được giải phóng cuối cùng (khi đối tượng là garbage garbage), ngay cả khi Vứt bỏ không bao giờ được gọi (ví dụ do ngoại lệ và không bảo vệ được khối mã). –

+1

@ TheDag: Mỗi tài nguyên không được quản lý cần dọn dẹp finalizer nên hầu như luôn luôn được đóng gói trong đối tượng riêng của nó, hoặc là lấy được từ 'Object' hoặc một kiểu cơ sở trừu tượng được thiết kế rõ ràng để hỗ trợ dọn dẹp như vậy. Kiểu kết quả sau đó sẽ là một tài nguyên được quản lý, mà một tham chiếu có thể được giữ bởi loại lớn hơn. Việc dọn dẹp cuối cùng sẽ được thực hiện bởi đối tượng đóng gói nhỏ hơn; đối tượng lớn hơn sẽ không cần một finalizer. – supercat

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