Finalize (Finalizer/Destructor)
- Method:
~ClassName() (Syntax C#)
- ถูกเรียกโดย Garbage Collector (GC) ก่อน Reclaim Memory
- ไม่รับประกันเวลา (Non-deterministic)
- ใช้ Cleanup Unmanaged Resources (File Handle, DB Connection, Native Pointer)
- เป็นของ
Object Class
- ไม่ควบคุมได้ เรียกบังคับได้ด้วย
GC.Collect() (ไม่แนะนำ - หยุด Performance)
Dispose (IDisposable Pattern)
- Method:
void Dispose() จาก Interface IDisposable
- เรียก Explicitly โดย Developer (Deterministic)
- Cleanup ทั้ง Managed และ Unmanaged Resources
- ใช้กับ
using Statement (Auto Dispose)
- ควรเรียก
GC.SuppressFinalize(this) เพื่อไม่ให้ GC เรียก Finalize ซ้ำ
ตัวอย่าง Finalize (Destructor)
public class Demo
{
~Demo() // Finalizer - C# Syntax
{
Console.WriteLine("Finalize called");
// Cleanup unmanaged resources only
}
}
ตัวอย่าง Dispose Pattern (Standard)
public class ResourceHolder : IDisposable
{
private bool _disposed = false;
private IntPtr _unmanagedHandle; // Unmanaged resource
private FileStream _managedResource; // Managed resource
public ResourceHolder()
{
_unmanagedHandle = AllocateUnmanagedResource();
_managedResource = new FileStream("data.txt", FileMode.Create);
}
// Public Dispose - เรียกโดย User Code
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this); // บอก GC ว่า Dispose แล้ว ไม่ต้อง Finalize
}
// Protected Virtual - ให้ Derived Class Override ได้
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
// Cleanup Managed Resources
_managedResource?.Dispose();
_managedResource = null;
}
// Cleanup Unmanaged Resources (เสมอ)
if (_unmanagedHandle != IntPtr.Zero)
{
FreeUnmanagedResource(_unmanagedHandle);
_unmanagedHandle = IntPtr.Zero;
}
_disposed = true;
}
}
// Finalizer - Fallback ถ้า User ลืม Dispose
~ResourceHolder()
{
Dispose(false); // disposing = false → Cleanup Unmanaged เท่านั้น
}
// P/Invoke Example
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
private static extern IntPtr AllocateUnmanagedResource();
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
private static extern void FreeUnmanagedResource(IntPtr handle);
}
การใช้งานกับ using Statement
// แบบเดิม (C# 7-)
using (var resource = new ResourceHolder())
{
// ใช้งาน resource
} // Dispose() เรียกอัตโนมัติที่นี่
// ใหม่ C# 8+ Using Declaration
using var resource = new ResourceHolder();
// Dispose เรียกตอนจบ Scope
สรุป: ควร Implement ทั้งคู่ (Microsoft Recommends)
- Dispose(): เรียกได้ทันที Deterministic Cleanup
- Finalize(): Safety Net ป้องกัน Resource Leak ถ้า User ลืม Dispose
สาระสำคัญ
| ด้าน | Finalize | Dispose |
| เรียกโดย | GC (Non-deterministic) | Developer (Deterministic) |
| Cleanup | Unmanaged Only | Managed + Unmanaged |
| Performance | Costly (Gen 2 Promotion) | รวดเร็ว |
| Exception | Swallowed by GC | Bubble up ปกติ |