zoukankan      html  css  js  c++  java
  • using关键字的使用

    using关键字的主要3个作用:

    • 引入命名空间
    • 创建别名
    • 强制资源清理

    一、引入命名空间: 

      命名空间是.NET程序在逻辑上的组织结构,而并非实际的物理结构,是一种避免类名冲突的方法,用于将不同的数据类型组合划分的方式。例如,在.NET中很多的基本类型都位于System命名空间,数据操作类型位于System.Data命名空间。

      using类似于Java语言的import指令,都是引入命名空间(Java中称作包)这种逻辑结构;而不同于C语言中的#include指令,用于引入实际的类库,using引入命名空间,并不等于编译器编译时加载该命名空间所在的程序集,程序集的加载决定于程序中对该程序集是否存在调用操作,如果代码中不存在任何调用操作则编译器将不会加载using引入命名空间所在程序集。因此,在源文件开头,引入多个命名空间,并非加载多个程序集,不会造成“过度引用”的弊端。

      命名空间分为两类:用户定义的命名空间和系统定义的命名空间。用户定义的命名空间是在代码中定义的命名空间。

    using System.Data;
    using System.Data.Sqlclient;//用于操作SQL数据库

    二、为命名空间或类型创建别名

      创建 using 别名,以便更易于将标识符限定到命名空间或类型。

      例子:新建一个控制台应用程序train_console,在.cs中添加如下代码:

    namespace People {
        namespace Sleeping {
            public class Sleep {
                public Sleep()
                {
                    Console.WriteLine("创建睡觉类");
                }
                public void SleepAll()
                {
                    Console.WriteLine("人都要睡觉的");
                }
            }
        }
    }

      在namespace trian_console中添加using引用的别名:

    using sleep = People.Sleeping;//为命名空间使用using别名

      在Main函数中添加:

    sleep.Sleep s = new sleep.Sleep();
    s.SleepAll();

      运行结果如下:

    三、强制资源清理

      C# 通过 .NET Framework 公共语言运行库 (CLR) 中的GC(Garbage Collection)自动释放用于存储不再需要的对象的内存。内存的释放具有不确定性;一旦 CLR 决定执行垃圾回收,就会释放内存。

      因为非托管资源不受GC控制,对象必须调用自己的Dispose()方法来释放,这就是所谓的Dispose模式。所以,通常最好尽快释放诸如文件句柄和网络连接这样的有限资源。

      using 语句允许程序员指定使用资源的对象应当何时释放资源。为 using 语句提供的对象必须实现IDisposable接口。此接口提供了Dispose()方法,该方法将释放此对象的资源。

      下面的示例显示用户定义类可以如何实现它自己的 Dispose 行为。注意类型必须从IDisposable继承。

      新建一个控制台应用程序,添加一个类C(用于测试using释放资源的过程):

    class C : IDisposable {
            public void UseLimitResource()
            {
                Console.WriteLine("使用有限的资源");
            }
            void IDisposable.Dispose()
            {
                Console.WriteLine("释放有限的资源");
            }
    }

      在Main中添加:

    Console.WriteLine("使用using释放资源:");
    using (C c = new C()) //释放资源 
    {
          c.UseLimitResource();
    }
    Console.WriteLine("资源成功释放!");

      运行结果如下:

    【规则】

    • using只能用于实现了IDisposable接口的类型,禁止为不支持IDisposable接口的类型使用using语句,否则会出现编译时错误;
    • using语句适用于清理单个非托管资源的情况,而多个非托管对象的清理最好以try-finnaly来实现,因为嵌套的using语句可能存在隐藏的Bug。内层using块引发异常时,将不能释放外层using块的对象资源。
    • using语句支持初始化多个变量,但前提是这些变量的类型必须相同

     

    using和try-catch-finally的使用异同

      try-catch-finally 一起使用的常见方式是:在try块中获取并使用资源,在catch块中处理异常情况,并在finally块中释放资源。

      共同点:都可以释放资源  
      不同点:
        try-catch-finally可以用来捕获异常并处理,using不行;
        using可以创建别名,导入命名空间 ,try-catch-finally不行;
        using会在资源超出范围后主动释放对象,try-catch-finally要程序员自己写释放对象的代码

    两者在处理操作数据库时的使用

      很明显,Dispose方法是一个外部方法,系统并不会帮你调用。为了尽早释放对象所占用的资源,所以需要保证Dispose方法能尽早被执行。那么在.Net中提供了一个比较简便的方法,就是对于实现了IDisposable接口的类型对象提供了using语句。
      对于操作数据库,使用using语句可以如下:

        using( SqlConnection sqlConn = new SqlConnection( yourConnectionString ) )
        {
            sqlConn.Open();//Open connection
            //Operate DB here using "sqlConn"   
            sqlConn.Close();//Close connection
        }

      但是有时候当多个对象需要释放的时候,例如:

        SqlConnection sqlConn = new SqlConnection( yourConnectionString );
        SqlCommand sqlComm = new SqlCommand( yourQueryString, sqlConn );
        using(sqlConn as IDisposable)
        using(sqlComm as IDisposable)
        {
            sqlConn.Open();//Open connection
            sqlComm.ExecuteNonQuery();//Operate DB here
        }

      这时候要特别注意,需要确保在发生异常的情况下,所有对象都能正常释放。显然,这段程序块,当构造“sqlComm”对象发生异常,会造成“sqlConn”对象无法及时被释放。虽说构造函数内部很少发生异常,或者说编写程序的时候要尽量避免从构造函数内向外散发异常。不过这里所说的意思是,要尽量把需要释放的对象放到using或者try-catch程序块,并作局部的异常处理,避免异常造成有些对象没有被释放。那么改进的方法,例如可以如下。

        using( SqlConnection sqlConn = new SqlConnection( yourConnectionString ) )
        using( SqlCommand sqlComm = new SqlCommand( yourQueryString, sqlConn ) )
        {
            try
            {
                sqlConn.Open();//Open connection
                sqlComm.ExecuteNonQuery();//Operate DB here
            }
            catch( SqlException err )
            {
                MessageBox.Show( err.Message );
            }
            catch( Exception err )
            {
                MessageBox.Show( err.Message );
            }
        }

      (如上,即使在构造“sqlComm”出现异常,也会释放“sqlConn”对象。)
      但是对于using程序块来说,它有两个限制。
        第一个就是using所对应的对象必须继承IDisposable,如果此对象没有继承IDisposable接口的话,系统会提示编译错误。
        例如:

      using( string strMsg = "My Test" )
      Debug.WriteLine( strMsg );//Can't be compiled

        第二个using对象检查是静态类型检查,并不支持运行时类型检查,因此如下形式也会出现编译错误。

        SqlConnection sqlConn = new SqlConnection( yourConnectionString );
        object objConn = sqlConn;
        using ( objConn )
        {
            Debug.WriteLine( objConn.ToString() );//Can't be compiled
        }

        不过对于后者,可以通过“as”来进行类型转换方式来改进。

        SqlConnection sqlConn = new SqlConnection( yourConnectionString );
        object objConn = sqlConn;
        using ( objConn as IDisposable )
        {
            Debug.WriteLine( objConn.ToString() );
        }

        对于Dispose函数的调用来说,使用using程序块来完成只是最常用的方法,除此外,还可以用try-finally来完成,例如:

        SqlConnection sqlConn = new SqlConnection( yourConnectionString );
        try
        {
            sqlConn.Open();
            //Operate DB here using "sqlConn"
        }
        finally
        {
            if( sqlConn != null )
                sqlConn.Dispose();
        }

      

    完整例子如下:

      新建一个控制台应用程序,再新建一个类using_sql,代码如下:

        class using_sql {
            private static string constr = "Data Source=.;Initial Catalog=Csharp;Persist Security Info=True;User ID=sa;Password=huang_bx";
            public static void SqlFun()
            {
                Console.WriteLine("使用using方法");
                using (SqlConnection conn = new SqlConnection(constr))
                {
                    conn.Open();
                    string cmdstr = "select * from users";
                    SqlCommand cmd = null;
                    try
                    {
                        cmd = new SqlCommand(cmdstr, conn);
                        SqlDataReader sdr = cmd.ExecuteReader();
                        while (sdr.Read())
                        {
                            Console.WriteLine("学号:{0}  姓名:{1}", sdr["UserID"].ToString().Trim(), sdr["UserName"].ToString().Trim());
                        }
                        Console.WriteLine("Connection还未关闭!");
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("command出现异常:{0}", ex.Message.ToString());
                    }
                    finally
                    {
                        cmd.Dispose();
                    }
                    Console.WriteLine("Connection已经关闭!");
                    Console.WriteLine();
                    Console.WriteLine();
                }
    
            }
    
            public static void sqltrycatch()
            {
                Console.WriteLine("使用try-catch-finally");
                //使用try-catch-finally
                SqlCommand cmd1 = null;
                SqlConnection conn1 = null;
                try
                {
                    conn1 = new SqlConnection(constr);
                    conn1.Open();
                    string cmdstr = "select * from users";
                    cmd1 = new SqlCommand(cmdstr, conn1);
                    SqlDataReader sdr = cmd1.ExecuteReader();
                    while (sdr.Read())
                    {
                        Console.WriteLine("学号:{0}  姓名:{1}", sdr["UserID"].ToString().Trim(), sdr["UserName"].ToString().Trim());
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine("command出现异常:{0}", e.Message.ToString());
                }
                finally
                {
                    cmd1.Dispose();
                    conn1.Dispose();
                }
            }
        }

      在Main函数中添加:

    //using 在 操作数据库时的使用
    Console.WriteLine("using 在操作数据库时的使用:");
    using_sql.SqlFun();
    using_sql.sqltrycatch();

      运行结果如下:

      为了及早释放对象所占用的非托管资源,因此要保证Dispose方法能在使用完对象后被调用,.Net提供了using程序块和try-finally程序块两个方法,两者并没有太大的区别,可能使用using能使程序看得比较简明,但是为了防止异常,需要在using中加入try-catch,这样反而不如try-finally看得舒服,不过这也只是我个人的看法。总的来说,只要把方法合理整合到应用程序当中才是最重要的。

    参考资料:百度百科

                    http://www.cnblogs.com/falla/archive/2010/02/01/1660832.html

     

  • 相关阅读:
    test
    男神zyh的青睐
    HH的项链
    PAT刷题经验
    LaTeX常用数学符号
    Battle Over Cities Hard Version
    Cut
    文本生成器
    Explorer Space
    2021.04.21
  • 原文地址:https://www.cnblogs.com/huangbx/p/2623451.html
Copyright © 2011-2022 走看看