利用using和try/finally语句来清理资源

使用非托管资源的类型必须实现IDisposable接口的Dispose()方法来精确的释放系统资源。.Net环境的这一规则使得释放资源代码的职责 是类型的使用者,而不是类型或系统。因此,任何时候你在使用一个有Dispose()方法的类型时,你就有责任来调用Dispose()方法来释放资源。 最好的方法来保证Dispose()被调用的结构是使用using语句或者try/finally块。

所有包含非托管资源的类型应该实现IDisposable接口,另外,当你忘记恰当的处理这些类型时,它们会被动的创建析构函数。如果你忘记处理这些对 象,那些非内存资源会在晚些时候,析构函数被确切调用时得到释放。这就使得这些对象在内存时待的时间更长,从而会使你的应用程序会因系统资源占用太多而速 度下降。

幸运的是,C#语言的设计者精确的释放资源是一个常见的任务。他们添加了一个关键字来使这变得简单了。假设你写了下面的代码:public void ExecuteCommand( string connString,  string commandString )

{

SqlConnection myConnection = new SqlConnection( connString );

SqlCommand mySqlCommand = new SqlCommand( commandString,  myConnection );

myConnection.Open();

mySqlCommand.ExecuteNonQuery();

}

这个例子中的两个可处理对象没有被恰当的释放:SqlConnection和SqlCommand。两个对象同时保存在内存里直到析构函数被调用。(这两 个类都是从System.ComponentModel.Component继承来的。)

解决这个问题的方法就是在使用完命令和链接后就调用它们的Dispose:

  1. public void ExecuteCommand( string connString,  string commandString )
  2. {
  3. SqlConnection myConnection = new SqlConnection( connString );
  4. SqlCommand mySqlCommand = new SqlCommand( commandString,
  5. myConnection );
  6. myConnection.Open();
  7. mySqlCommand.ExecuteNonQuery();
  8. mySqlCommand.Dispose( );
  9. myConnection.Dispose( );
  10. }

这很好,除非SQL命令在执行时抛出异常,这时你的Dispose()调用就永远不会成功。using语句可以确保Dispose()方法被调用。当你把 对象分配到using语句内时,C#的编译器就把这些对象放到一个try/finally块内:

  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. }

当你在一个函数内使用一个可处理对象时,using语句是最简单的方法来保证这个对象被恰当的处理掉。当这些对象被分配时,会被编译器放到一个 try/finally块中。下面的两段代码编译成的IL是一样的

  1. SqlConnection myConnection = null;
  2. // Example Using clause:
  3. using ( myConnection = new SqlConnection( connString ))
  4. {
  5. myConnection.Open();
  6. }
  7. // example Try / Catch block:
  8. try {
  9. myConnection = new SqlConnection( connString );
  10. myConnection.Open();
  11. }
  12. finally {
  13. myConnection.Dispose( );
  14. }

如果你把一个不能处理类型的变量放置在using语句内,C#编译器给出一个错误,例如:

  1. // Does not compile:
  2. // String is sealed, and does not support IDisposable.
  3. using( string msg = "This is a message" )
  4. Console.WriteLine( msg );

using只能在编译时,那些支持IDispose接口的类型可以使用,并不是任意的对象

  1. // Does not compile.
  2. // Object does not support IDisposable.
  3. using ( object obj = Factory.CreateResource( ))
  4. Console.WriteLine( obj.ToString( ));

如果obj实现了IDispose接口,那么using语句就会生成资源清理代码,如果不是,using就退化成使用using(null),这是安全 的,但没有任何作用。如果你对一个对象是否应该放在using语句中不是很确定,宁可为了更安全:假设要这样做,而且按前面的方法把它放到using语句 中。

这里讲了一个简单的情况:无论何时,当你在某个方法内使用一个可处理对象时,把这个对象放在using语句内。现在你学习一些更复杂的应用。还是前面那个 例子里须要释放的两个对象:链接和命令。前面的例子告诉你创建了两个不同的using语句,一个包含一个可处理对象。每个using语句就生成了一个不同 的try/finally块。等效于你写了这样的代码:

  1. public void ExecuteCommand( string connString,
  2. string commandString )
  3. {
  4. SqlConnection myConnection = null;
  5. SqlCommand mySqlCommand = null;
  6. try
  7. {
  8. myConnection = new SqlConnection( connString );
  9. try
  10. {
  11. mySqlCommand = new SqlCommand( commandString,
  12. &nbs
时间: 2024-08-03 07:15:12

利用using和try/finally语句来清理资源的相关文章

利用反射+多态替换条件语句

/*利用反射+多态替换条件语句*/ class Program { public static void Main(string[] args) { /* * 用户发送一个命令,让代码去指定Commander * * <?xml version="1.0" encoding="utf-8" ?><Command><CommandType>Start</CommandType></Command> */ //

JS利用短路原理简写if语句

看GoogleDoodle-Dance的源代码,学习到一个小知识——简写if语句. 几乎所有语言中||和&&都遵循“短路”原理,如&&中第一个表达式为假就不会去处理第二个表达式,而||正好相反. js也遵循上述原则.所有: a && b : 将a, b转换为Boolean类型, 再执行逻辑与, true返回b, false返回aa || b : 将a, b转换为Boolean类型, 再执行逻辑或, true返回a, false返回b 所以类似于这样的if语句

9.3.2 用 IDisposable 接口清理资源

我们已经使用过几种实现了 IDisposable 接口的类型,比如,Graphics 和 SolidBrush.我们想使代码尽可能易于理解,因此,当使用完对象时,我们就显式调用 Dispose 方法. C# 中包含了语法糖,以 using 语句的形式,保证了即使语句体内抛出异常,也能调用 Dispose:F# 有相似的结构,用 use 关键字.清单 9.11 是一个处理文件的简单示例. Listing 9.11 使用 use 关键字处理文件 (F#Interactive) > open Syst

读书笔记利用T-SQL语句快速清理ZBLOG程序的SQL SERVER2012数据库内容

最近使用了ZBLOG+SQL SERVER搭建了一个博客系统,采用的是ASP程序,因为我数据量很小,使用插件生成HTML文件的话,就没有必要使用PHP了,而且我上次也讲过,PHP的博客程序存在一些问题,很消耗资源,而且数据量也不能做的很大,更重要的是静态化还是不能抵抗流量的冲击. 环境配置:windows server服务器+ZBLOG ASP程序+SQL SERVER2012数据库+域名(读后感http://www.simayi.net读书笔记)+读书主题. 好了,下面还是讲述我最近学习的T-

利用T-SQL语句快速清理ZBLOG程序的SQL SERVER2012数据库内容

最近使用了ZBLOG+SQL SERVER搭建了一个博客系统,采用的是ASP程序,因为我数据量很小,使用插件生成HTML文件的话,就没有必要使用PHP了,而且我上次也讲过,PHP的博客程序存在一些问题,很消耗资源,而且数据量也不能做的很大,更重要的是静态化还是不能抵抗流量的冲击.环境配置:windows server服务器+ZBLOG ASP程序+SQL SERVER2012数据库+域名((读后感http://www.simayi.net读书笔记))+读书主题.好了,下面还是讲述我最近学习的T-

利用dbms_metadata.get_ddl查看DDL语句

当我们想要查看某个表或者是表空间的DDL的时候,可以利用dbms_metadata.get_ddl这个包来查看. dbms_metadata包中的get_ddl函数详细参数GET_DDL函数返回创建对象的原数据的DDL语句,详细参数如下-- object_type ---需要返回原数据的DDL语句的对象类型-- name --- 对象名称-- schema ---对象所在的Schema,默认为当前用户所在所Schema-- version ---对象原数据的版本-- model ---原数据的类

Oracle利用dbms_metadata.get_ddl查看DDL语句

当我们想要查看某个表或者是表空间的DDL的时候,可以利用dbms_metadata.get_ddl这个包来查看. dbms_metadata包中的get_ddl函数详细参数 GET_DDL函数返回创建对象的原数据的DDL语句,详细参数如下 -- object_type ---需要返回原数据的DDL语句的对象类型 -- name --- 对象名称 -- schema ---对象所在的Schema,默认为当前用户所在所Schema -- version ---对象原数据的版本 -- model --

powershell利用winform批量执行tsql语句

#加载.net的winform模块 [Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") $app=[System.Windows.Forms.Application]$myForm=new-object System.Windows.Forms.Form$myForm.Text="T_sql Excute window" #执行程序的按钮 $button1 = new-object S

利用 force index优化sql语句性能

今天写了一个统计sql,在一个近亿条数据的表上执行,200s都查不出结果.SQL如下: select customer,count(1) c from upv_** where created between "2015-07-06" and "2015-07-07" group by customer having c > 20 order by c desc 执行explain,发现这个sql扫描了8000W条记录到磁盘上.然后再进行筛选. 拿着这个SQL