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

  • 相关阅读:
    数据库事务的四大特性
    Mysql数据库的慢sql优化步骤
    数据库事务的4大隔离级别
    mysql的命令练习
    通过jedis对redis客户端的一些基本操作
    通过jedisPool写一个redis连接池
    jedis
    maven将本地jar包添加到本地仓库
    [Django学习] Django基础(7)_分类统计
    [Django学习] Django基础(6)_Field lookups
  • 原文地址:https://www.cnblogs.com/miniwiki/p/1734307.html
Copyright © 2011-2022 走看看