Dấu ngã trước tên hàm có nghĩa gì trong C #?


164

Tôi đang xem một số mã và nó có tuyên bố này:

~ConnectionManager()
{
    Dispose(false);
}

Lớp này thực hiện IDisposablegiao diện, nhưng tôi không biết đó có phải là một phần của dấu ngã (~) được sử dụng cho không.

Câu trả lời:


213

~ là kẻ hủy diệt

  1. Các cấu trúc hủy được gọi tự động và không thể được gọi một cách rõ ràng.
  2. Phá hủy không thể bị quá tải. Vì vậy, một lớp có thể có tối đa một hàm hủy.
  3. Kẻ hủy diệt không được thừa kế. Vì vậy, một lớp không có hàm hủy nào khác ngoài lớp, có thể được khai báo trong nó.
  4. Phá hủy không thể được sử dụng với cấu trúc. Chúng chỉ được sử dụng với các lớp. Một thể hiện trở thành đủ điều kiện để hủy khi không còn mã nào có thể sử dụng thể hiện đó nữa.
  5. Việc thực thi hàm hủy đối với thể hiện có thể xảy ra bất cứ lúc nào sau khi thể hiện đủ điều kiện để hủy.
  6. Khi một thể hiện bị hủy, các hàm hủy trong chuỗi kế thừa của nó được gọi, theo thứ tự, từ hầu hết dẫn xuất đến dẫn xuất ít nhất.

Hoàn thiện

Trong C #, phương thức Finalize thực hiện các hoạt động mà một hàm hủy C ++ tiêu chuẩn sẽ làm. Trong C #, bạn không đặt tên là Hoàn thiện - bạn sử dụng cú pháp hàm hủy C ++ để đặt ký hiệu dấu ngã (~) trước tên của lớp.

Vứt bỏ

Tốt nhất là loại bỏ các đối tượng trong một Close()hoặc một Dispose()phương thức có thể được gọi rõ ràng bởi người dùng của lớp. Hoàn thiện (hàm hủy) được gọi bởi GC.

Các IDisposable giao diện nói với thế giới rằng lớp học của bạn giữ lên các nguồn tài nguyên mà cần phải được xử lý và cung cấp cho người dùng một cách để phát hành chúng. Nếu bạn cần phải thực hiện một trình hoàn thiện trong lớp của mình, phương thức Vứt bỏ của bạn nên sử dụng GC.SuppressFinalize()phương thức để đảm bảo rằng việc hoàn tất cá thể của bạn bị triệt tiêu.

Dùng gì?

Việc gọi một kẻ hủy diệt một cách rõ ràng là không hợp pháp. Trình hủy của bạn sẽ được gọi bởi trình thu gom rác. Nếu bạn xử lý các tài nguyên không được quản lý quý giá (như xử lý tệp) mà bạn muốn đóng và xử lý càng nhanh càng tốt, bạn nên triển khai giao diện IDis Dùng một lần.


3
Tôi không biết nó đã từng như thế nào trong quá khứ. Nhưng bây giờ các tàu khu trục được thừa kế. Kiểm tra liên kết này để biết thêm thông tin (kiểm tra ví dụ ở cuối): msdn.microsoft.com/en-us/l
Library / 66x5fx1b.aspx

1
@RononDex điểm 3 của chính trang bạn liên kết đến các trạng thái "Người hoàn thiện không thể được thừa kế" , điều này mâu thuẫn với nhận xét của bạn. Tất cả đều hơi khó hiểu vì mặc dù chúng không thể được thừa kế, " Finalizephương thức này được gọi đệ quy cho tất cả các trường hợp trong chuỗi thừa kế, từ dẫn xuất nhiều nhất đến dẫn xuất ít nhất" . Tuy nhiên, xin lưu ý rằng đó không phải là hành vi giống như bạn nhận được từ các hàm hủy kế thừa.
Đánh dấu Amery

@MarkAmery ah Tôi hiểu rồi, vậy về cơ bản họ có được gọi theo thứ tự đảo ngược so với thứ được thừa kế không?
RononDex

45

Đây là một quyết toán . Thành thật mà nói, bạn rất hiếm khi cần phải viết một bộ hoàn thiện. Bạn thực sự chỉ cần viết một nếu:

  • Bạn có quyền truy cập trực tiếp vào một tài nguyên không được quản lý (ví dụ thông qua một IntPtr) và bạn không thể sử dụng SafeHandlenó giúp việc này dễ dàng hơn
  • Bạn đang thực hiện IDisposabletrong một lớp không niêm phong. (Sở thích của tôi là niêm phong các lớp trừ khi chúng được thiết kế để kế thừa.) Bộ hoàn thiện là một phần của mẫu Loại bỏ chính tắc trong các trường hợp như vậy.

9

Nó được sử dụng để chỉ ra hàm hủy cho lớp.


12
Cả hai đều đúng, tùy thuộc vào thông số C # mà bạn đọc. MS one gần đây nhất (thống nhất C # 3.0) gọi chúng là các hàm hủy (ví dụ: phần 10.13) nhưng thông số ECMA gọi chúng là các bộ hoàn thiện.
Jon Skeet

@ 1800INFORMATION: Phần tử cú pháp được gọi đúng là hàm hủy. Nếu một lớp có hàm hủy, trình biên dịch C # sẽ tự động tạo một bộ hoàn thiện bao gồm một try/finallykhối thường vô dụng để đảm bảo rằng Finalizephương thức cha được gọi. Hầu hết những điều đúng với kẻ hủy diệt đều đúng với người hoàn thiện, và ngược lại, nhưng những từ này có nghĩa là những điều hơi khác nhau.
supercat

4

Giống như C ++, nó là hàm hủy; tuy nhiên trong C # bạn không gọi nó một cách rõ ràng, nó được gọi khi đối tượng được thu thập.



Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.