Trong .NET, tôi nên sử dụng trong trường hợp GC.SuppressFinalize()
nào?
Những lợi thế nào khi sử dụng phương pháp này mang lại cho tôi?
Trong .NET, tôi nên sử dụng trong trường hợp GC.SuppressFinalize()
nào?
Những lợi thế nào khi sử dụng phương pháp này mang lại cho tôi?
Câu trả lời:
SuppressFinalize
chỉ nên được gọi bởi một lớp có bộ hoàn thiện. Nó thông báo cho Bộ sưu tập rác (GC) rằng this
đối tượng đã được dọn sạch hoàn toàn.
Mẫu được đề xuất IDisposable
khi bạn có bộ hoàn thiện là:
public class MyClass : IDisposable
{
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
// called via myClass.Dispose().
// OK to use any private object references
}
// Release unmanaged resources.
// Set large fields to null.
disposed = true;
}
}
public void Dispose() // Implement IDisposable
{
Dispose(true);
GC.SuppressFinalize(this);
}
~MyClass() // the finalizer
{
Dispose(false);
}
}
Thông thường, CLR giữ các tab trên các đối tượng bằng bộ hoàn thiện khi chúng được tạo (khiến chúng đắt hơn khi tạo). SuppressFinalize
nói với GC rằng đối tượng đã được dọn sạch đúng cách và không cần phải đi vào hàng đợi hoàn thiện. Nó trông giống như một hàm hủy của C ++, nhưng không hoạt động giống như một.
Việc SuppressFinalize
tối ưu hóa không phải là nhỏ, vì các đối tượng của bạn có thể sống rất lâu chờ đợi trên hàng đợi hoàn thiện. Đừng cố gắng kêu gọi SuppressFinalize
các đối tượng khác nhớ bạn. Đó là một khiếm khuyết nghiêm trọng đang chờ xảy ra.
Hướng dẫn thiết kế thông báo cho chúng tôi rằng bộ hoàn thiện là không cần thiết nếu đối tượng của bạn thực hiện IDisposable
, nhưng nếu bạn có bộ hoàn thiện, bạn nên thực hiện IDisposable
để cho phép dọn dẹp xác định lớp của bạn.
Hầu hết thời gian bạn sẽ có thể thoát khỏi IDisposable
để làm sạch tài nguyên. Bạn chỉ cần một bộ hoàn thiện khi đối tượng của bạn giữ các tài nguyên không được quản lý và bạn cần đảm bảo các tài nguyên đó được dọn sạch.
Lưu ý: Đôi khi các lập trình viên sẽ thêm một bộ hoàn thiện để gỡ lỗi các bản dựng của các IDisposable
lớp của riêng họ để kiểm tra mã đó đã xử lý IDisposable
đúng đối tượng của họ .
public void Dispose() // Implement IDisposable
{
Dispose(true);
#if DEBUG
GC.SuppressFinalize(this);
#endif
}
#if DEBUG
~MyClass() // the finalizer
{
Dispose(false);
}
#endif
IDisposable
là không sealed
, thì nó sẽ bao gồm lệnh gọi GC.SuppressFinalize(this)
ngay cả khi nó không bao gồm một trình hoàn thiện do người dùng định nghĩa . Điều này là cần thiết để đảm bảo ngữ nghĩa phù hợp cho các loại dẫn xuất thêm trình hoàn thiện do người dùng xác định nhưng chỉ ghi đè Dispose(bool)
phương thức được bảo vệ .
sealed
đề cập bởi @SamHarwell là quan trọng, đối với các lớp dẫn xuất. Kết quả CodeAnalysis trong ca1816 + ca1063 khi lớp không được niêm phong, nhưng các lớp niêm phong vẫn ổn mà không có SuppressFinalize
.
SupressFinalize
nói với hệ thống rằng bất kỳ công việc nào đã được thực hiện trong bộ hoàn thiện đã được thực hiện, vì vậy bộ hoàn thiện không cần phải được gọi. Từ các tài liệu .NET:
Các đối tượng triển khai giao diện IDis Dùng một lần có thể gọi phương thức này từ phương thức IDisydia.Dispose để ngăn trình thu gom rác gọi Object.Finalize trên một đối tượng không yêu cầu.
Nói chung, hầu hết mọi Dispose()
phương thức đều có thể gọi GC.SupressFinalize()
, bởi vì nó sẽ dọn sạch mọi thứ sẽ được dọn sạch trong bộ hoàn thiện.
SupressFinalize
chỉ là một cái gì đó cung cấp tối ưu hóa cho phép hệ thống không bận tâm xếp hàng đối tượng vào luồng hoàn thiện. Một văn bản Dispose()
/ quyết toán đúng sẽ hoạt động đúng có hoặc không có cuộc gọi đến GC.SupressFinalize()
.
Phương thức đó phải được gọi trên Dispose
phương thức của các đối tượng thực hiện IDisposable
, theo cách này, GC sẽ không gọi bộ hoàn thiện vào lần khác nếu có người gọi Dispose
phương thức đó.
Xem: Phương pháp GC.SuppressFinalize (Object) - Microsoft Docs
Dispose(true);
GC.SuppressFinalize(this);
Nếu đối tượng có bộ hoàn thiện, .net sẽ đặt tham chiếu trong hàng đợi hoàn thiện.
Vì chúng tôi có cuộc gọi Dispose(ture)
, đối tượng rõ ràng, vì vậy chúng tôi không cần hàng đợi quyết toán để thực hiện công việc này.
Vì vậy, gọi GC.SuppressFinalize(this)
loại bỏ tham chiếu trong hàng đợi quyết toán.
Nếu một lớp, hoặc bất cứ thứ gì có nguồn gốc từ nó, có thể giữ tham chiếu trực tiếp cuối cùng đến một đối tượng bằng bộ hoàn thiện, thì GC.SuppressFinalize(this)
hoặc GC.KeepAlive(this)
sẽ được gọi trên đối tượng sau bất kỳ thao tác nào có thể bị ảnh hưởng bất lợi bởi bộ hoàn thiện đó, do đó đảm bảo rằng bộ hoàn thiện đã thắng Sẽ chạy cho đến khi hoạt động đó hoàn tất.
Chi phí GC.KeepAlive()
và GC.SuppressFinalize(this)
về cơ bản là giống nhau trong bất kỳ lớp nào không có bộ hoàn thiện và các lớp thường có bộ hoàn thiện nên thường gọi GC.SuppressFinalize(this)
, vì vậy sử dụng hàm sau làm bước cuối cùng Dispose()
có thể không phải lúc nào cũng cần thiết, nhưng nó sẽ không sai.