IDisposable.Dispose
对于非托管资源
建立和释放,C# 约定由 Dispose 方法来处理。
当类库中涉及到非托管资源,就应实现 Dispose 方法,来定义资源释放逻辑。
using 用来管理实现了 Dispose 方法的类,编译器会在作用域结束时调用 Dispose 方法。
非托管资源包括:网络请求,数据库连接,句柄等。
标准 dispose 模式
- 析构函数中调用 dispose 方法,托底防忘记调用;
- dispose 中最后要调用 GC.SuppressFinaliza 方法,通知 CLR 无需执行析构函数,因为清除工作已完成;
- 多次调用 dispose 应该是安全的,dispose 方法调用后,后续再调用都不会执行额外的工作;
- dispose 方法有 2 个重载:public 和 protected,protected 真实清除,public 调用 protected;
- 析构函数调用 protected;
- protected 的 bool 参数区分是被析构函数调用(false)还是被 public 调用(true);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| using System; using System.Runtime.InteropServices;
namespace MyConsole.DisposeDemo { public class SomeManagedResource { public SomeManagedResource(string name) { Name = name; }
public string Name { get; } }
public class MyUnmanagedResource : IDisposable { private IntPtr someUnmanagedResource = Marshal.AllocHGlobal(100); private SomeManagedResource managedResource = new SomeManagedResource("这是托管资源"); protected bool baseDisposed = false;
public void Dispose() { Dispose(true); GC.SuppressFinalize(this); }
protected virtual void Dispose(bool isDisposing) { if (baseDisposed) { return; } if (isDisposing) { if (managedResource != null) { managedResource = null; } } if (someUnmanagedResource != IntPtr.Zero) { Marshal.FreeHGlobal(someUnmanagedResource); someUnmanagedResource = IntPtr.Zero; } baseDisposed = true; }
~MyUnmanagedResource() { Dispose(false); } } }
|
Finalize
- 无法显式的重写 Finalize 方法,只能通过析构函数语法形式来实现。
- struct 中不允许定义析构函数,只有 class 中才可以,并且只能有一个。
- Finalize 方法不能被继承或重载。
- 执行垃圾回收之前系统会自动执行 Finalize 操作。
- Finalize 方法会极大地损伤性能。