zoukankan      html  css  js  c++  java
  • C# Using与Try..Finally 语句探究

       以前看书上说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 ([
    0] class [System.Data]System.Data.SqlClient.SqlConnection conn,
    [
    1] bool 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....."

  • 相关阅读:
    学习方法和阶段介绍 、 iOS界面开发引入 、 构造第一个App 、 视图控制器和视图 、 控件与事件 、 InterfaceBuilder
    Runtime 、 Block
    NSDictionary 、 NSMutableDictionary
    NSArray(二) 、 NSMutableArray 、 NSSet 、 NSMutableSet
    NSNumber 、 NSValue 、 日期处理 、 集合类 、 NSArray(一)
    (Foundation)NSObject 、 NSString 、 NSMutableString
    Objective-c---分类 、 扩展 、 ARC
    Objective-C--- 多态 、 协议
    关于Quartz2D方法小总结
    控制器之间的顺传与逆传
  • 原文地址:https://www.cnblogs.com/miniwiki/p/1734307.html
Copyright © 2011-2022 走看看