Effective C# Item15:利用using和try/finally语句来清理资源

来源:互联网 发布:淘宝手机访客 编辑:程序博客网 时间:2024/05/17 02:38

    在内存资源分配方面,.NET可以分为托管资源和非托管资源两部分。对于托管资源,.NET框架会负责进行垃圾回收的工作;对于非托管的资源,我们需要手动去释放资源。通常情况下,我们使用IDisposable接口中的Dispose()方法释放资源,而调用Dispose()方法的责任,由资源的拥有者或者对象的拥有者执行,即我们这些程序员,确保调用Dispose()方法的最佳方式就是使用using或者try/finally语句块。

    所有拥有非托管资源的类型,都应该实现IDisposable接口,另外作为一种保障措施,这种类型还会创建一个终结器,以防止我们忘记调用Dispose()方法,如果我们忘记了调用Dispose()方法,那么其中的非内存资源会在随后终结器执行时被释放。这样对象在内存中存留的时间会比较长,应用程序对资源的清理也比较慢。

    我们可以使用using的方式来强制调用Dispose()方法,查看以下代码。

public void ExecuteCommand( string connString,  string commandString ){  using ( SqlConnection myConnection = new    SqlConnection( connString ))  {    using ( SqlCommand mySqlCommand = new      SqlCommand( commandString,      myConnection ))    {      myConnection.Open();      mySqlCommand.ExecuteNonQuery();    }  }}


    上述代码中,SqlConnection和SqlCommand是两个需要释放资源的地方,其中在变量声明时,使用了using,它的作用和以下的代码相同。

SqlConnection myConnection = null;// Example Using clause:using ( myConnection = new SqlConnection( connString )){  myConnection.Open();}// example Try / Catch block:try {  myConnection = new SqlConnection( connString );  myConnection.Open();}finally {  myConnection.Dispose( );}


    注意,如果我们对一个没有实现IDisposable接口的对象使用using语句,那么C#编译器会产生错误,只有当编译时类型实现了IDisposable接口时,using语句才会正常编译。

    我们可以使用as进行类型转换,以防止出现编译错误。

 object obj = Factory.CreateResource( ); using ( obj as IDisposable ) Console.WriteLine( obj.ToString( ));


    上述代码中,如果obj没有实现IDisposable接口,那么变为using(null),这种做法很安全,不会产生变异错误,只是不会做任何事情。

    在释放某些对象的资源时,我们会发现有些类型既支持Dispose()方法,也支持Close()方法,例如SqlConnection类型,我们也可以通过调用Close()方法来释放资源。

    Dispose()方法和Close()方法的区别:Dispose()方法除了释放资源之外,还会通知垃圾收集器对该对象不再需要执行终结操作,它是通过调用GC.SuppressFinalize()方法来实现的;Close()方法一般不会这么处理,因此在调用了Close()方法的对象,依然会停留在终结队列中。因此,我们应该优先调用Dispose()方法。

    Dispose()方法不会将对象从内存上删除,它只是让对象释放非托管资源,这意味着如果释放的是仍被使用的对象,那么可能会遇到一些问题,因此,我们不应该释放那些仍然被程序其他地方引用的对象。

 

0 0
原创粉丝点击