Effective C# Item15:利用using和try/finally语句来清理资源
在内存资源分配方面,.NET可以分为托管资源和非托管资源两部分。对于托管资源,.NET框架会负责进行垃圾回收的工作;对于非托管的资源,我们需要手动去释放资源。通常情况下,我们使用IDisposable接口中的Dispose()方法释放资源,而调用Dispose()方法的责任,由资源的拥有者或者对象的拥有者执行,即我们这些程序员,确保调用Dispose()方法的最佳方式就是使用using或者try/finally语句块。
所有拥有非托管资源的类型,都应该实现IDisposable接口,另外作为一种保障措施,这种类型还会创建一个终结器,以防止我们忘记调用Dispose()方法,如果我们忘记了调用Dispose()方法,那么其中的非内存资源会在随后终结器执行时被释放。这样对象在内存中存留的时间会比较长,应用程序对资源的清理也比较慢。
我们可以使用using的方式来强制调用Dispose()方法,查看以下代码。
1 public void ExecuteCommand( string connString,
2 string commandString )
3 {
4 using ( SqlConnection myConnection = new
5 SqlConnection( connString ))
6 {
7 using ( SqlCommand mySqlCommand = new
8 SqlCommand( commandString,
9 myConnection ))
10 {
11 myConnection.Open();
12 mySqlCommand.ExecuteNonQuery();
13 }
14 }
15 }
1 SqlConnection myConnection = null;
2
3 // Example Using clause:
4 using ( myConnection = new SqlConnection( connString ))
5 {
6 myConnection.Open();
7 }
8
9 // example Try / Catch block:
10 try {
11 myConnection = new SqlConnection( connString );
12 myConnection.Open();
13 }
14 finally {
15 myConnection.Dispose( );
16 }
我们可以使用as进行类型转换,以防止出现编译错误。
1 object obj = Factory.CreateResource( );
2 using ( obj as IDisposable )
3 Console.WriteLine( obj.ToString( ));
在释放某些对象的资源时,我们会发现有些类型既支持Dispose()方法,也支持Close()方法,例如SqlConnection类型,我们也可以通过调用Close()方法来释放资源。
Dispose()方法和Close()方法的区别:Dispose()方法除了释放资源之外,还会通知垃圾收集器对该对象不再需要执行终结操作,它是通过调用GC.SuppressFinalize()方法来实现的;Close()方法一般不会这么处理,因此在调用了Close()方法的对象,依然会停留在终结队列中。因此,我们应该优先调用Dispose()方法。
Dispose()方法不会将对象从内存上删除,它只是让对象释放非托管资源,这意味着如果释放的是仍被使用的对象,那么可能会遇到一些问题,因此,我们不应该释放那些仍然被程序其他地方引用的对象。