More Effective C# Item5 : 确保泛型类型支持可销毁对象
泛型中,约束能够为你和用户完成两件事情:1. 约束能将运行时错误转换成编译时错误;2. 约束为用户清楚的给出了实例化类型参数所必须实现的功能。不过约束却没有能够限制类型参数不能够做什么。好在大多数情况下,我们无需关系除了必要功能之外,类型参数还附带了哪些额外功能。
但是如果泛型的约束中,包含了new约束,那么我们需要查看泛型参数是否实现了IDisposable接口。
我们来看下面的代码。

1 public interface IEngine
2 {
3 void DoWork();
4 }
5
6 public class EngineDriver<T> where T : IEngine, new()
7 {
8 public void GetThingsDone()
9 {
10 T driver = new T();
11 driver.DoWork();
12 }
13 }
上述代码在执行后,如果T实现了IDisposable接口,那么很可能会造成资源泄漏,因为约束中并没有说明泛型参数需要实现IDisposable接口,因此从编译器的角度来看,是不会调用Dispose()方法的。这样无论何时初始化本地变量后,我们都需要检查T是否实现了IDisposable接口。
下面是修改后的GetThingsDone()方法。
1 public void GetThingsDone()
2 {
3 T driver = new T();
4 using (driver as IDisposable)
5 {
6 driver.DoWork();
7 }
8 }
上述代码在编译时会为driver分配一个本地变量,用来存放将driver强制转换为IDisposable后的结果。如果T没有实现IDisposable接口,那么本地变量就是null,这时编译器是不会调用Dispose()方法的;如果T实现了IDisposable接口,那么编译器将在该代码块的结束位置生成对Dispose()方法的调用。
当然,针对上面提的问题,我们可以修改泛型类,使其实现IDisposable接口,来看下面的代码。

1 public class EngineDriver<T> : IDisposable where T : IEngine, new()
2 {
3 private T driver = null;
4 public void GetThingsDone()
5 {
6 if (driver == null)
7 {
8 driver = new T();
9 }
10 driver.DoWork();
11 }
12
13 #region IDisposable Members
14
15 public void Dispose()
16 {
17 IDisposable temp = driver as IDisposable;
18 if (temp != null)
19 {
20 temp.Dispose();
21 }
22 }
23
24 #endregion
25 }
需要注意,上述代码中,并不能保证不会重复调用driver的Dispose()方法,实现IDisposable接口的类,必须支持多次调用Dispose()方法,因为T并没有class约束,因此在离开Dispose()方法之前,并不能将driver设置为null。
总结:有时,你可以通过重构并让泛型类中不再创建实例来解决这个问题。而对于必须要使用到局部变量的时候,则要提供必要的销毁代码。若是泛型类还需要支持对实现IDisposable接口的泛型参数进行延迟创建的话,那么将会带来更多的工作,但是这是不可缺少的。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通