C# Using与Try..Finally 语句(转)

转自:http://www.cnblogs.com/miniwiki/archive/2010/05/13/1734307.html

Using实质是编译器生成Try{} Finally{},保证Finally始终执行。


复制代码
1 SqlDataReader   Func()
 
2         {
 
3 
 
4             using (SqlConnection conn=new SqlConnection())
 
5             {
 
6                 conn.Open();
 
7                 using (SqlCommand comm=new SqlCommand())
 
8                 {
 
9                     //............省略若干初始化
10                     SqlDataReader dr= comm.ExecuteReader();
11                     return dr;
12                 }
13                 
14             }
15         }
复制代码
本以为return了之后using就不会dispose对象了,没想到返回的SqlDataReader已经关闭连接了。于是查了查MSDN看到下面一段示例:

复制代码
使用using语句实际上生成的IL代码中是一个try, finally代码块,在finally代码块里释放资源。

比如这样一段代码:

            
using (SqlConnection conn = new SqlConnection())
            {
                conn.Open();
                
throw new Exception("Exception!!");//抛出异常之后能回收SqlConnection对象的资源吗?
            }

IL 代码可为:

  
// Code size       42 (0x2a)
  .maxstack  2
  .locals init ([
0class [System.Data]System.Data.SqlClient.SqlConnection conn,
           [
1bool CS$4$0000)
  IL_0000:  nop
  IL_0001:  newobj     instance 
void [System.Data]System.Data.SqlClient.SqlConnection::.ctor()
  IL_0006:  stloc.
0
  .
try
  {
    IL_0007:  nop
    IL_0008:  ldloc.
0
    IL_0009:  callvirt   instance 
void [System.Data]System.Data.Common.DbConnection::Open()
    IL_000e:  nop
    IL_000f:  ldstr      
"Exception!!"
    IL_0014:  newobj     instance 
void [mscorlib]System.Exception::.ctor(string)
    IL_0019:  
throw
  }  
// end .try
  finally
  {
    IL_001a:  ldloc.
0
    IL_001b:  ldnull
    IL_001c:  ceq
    IL_001e:  stloc.
1
    IL_001f:  ldloc.
1
    IL_0020:  brtrue.s   IL_0029
    IL_0022:  ldloc.
0
    IL_0023:  callvirt   instance 
void [mscorlib]System.IDisposable::Dispose()
    IL_0028:  nop
    IL_0029:  endfinally
  }  
// end handler 

可以看到调用了SqlConnection的Dispose方法释放了资源。
复制代码

说明using语句不论语句块里面是否return,均会生成资源释放的代码。Try。。Finally块也一样,也是先执行完Finally,再执行try里面可能有的return;

 

下面的代码证实了这一点:


复制代码
class Program
    {
        
static void Main(string[] args)
        {
            
using (UsingTest ut=  testFunc())
            {
                
            }  

        }

      
static UsingTest  testFunc()
       {
           
try{
               UsingTest ut 
= new UsingTest();
               
return ut;
           }
          
finally
            {

                Console.WriteLine(
"finally...");
                
            }
           
return null;//这里的代码始终无法访问到,说明try里面的return实际上是执行完finally后立即执行的
       }
    }

    
internal class UsingTest:IDisposable
    {


      
public  UsingTest()
        {
            Console.WriteLine(
"Constructing...");
        }
      
public  void Dispose()
       {
           Console.Write(
"Disposing.....");
       }
    }
复制代码

程序输出:

 

"Constructing..."

"finally..."

"Disposing....."

posted @ 2013-06-02 11:00  赤狐(zcm123)  阅读(174)  评论(0编辑  收藏  举报