C#中using关键字的作用及其用法
using的用途和使用技巧。
using关键字微软MSDN上解释总共有三种用途:
1、引用命名空间。
2、为命名空间或类型创建别名。
3、使用using语句。
1、引用命名空间,这样就可以直接在程序中引用命名空间的类型而不必指定详细的命名空间。
这个就不用说了吧,比如大家最常用的:using System.Text;
2、为命名空间或类型创建别名:
当同一个cs引用了不同的命名空间,但这些命名控件都包括了一个相同名字的类型的时候,可以使用using关键字来创建别名,这样会使代码更简洁。注意:并不是说两个名字重复,给其中一个用了别名,另外一个就不需要用别名了,如果两个都要使用,则两个都需要用using来定义别名的。
- using System;
- using aClass = NameSpace1.MyClass;
- using bClass = NameSpace2.MyClass;
- ......
- //使用方式
- aClass my1 = new aClass();
- Console.WriteLine(my1);
- bClass my2 = new bClass();
- Console.WriteLine(my2);
3、使用using语句,定义一个范围,在范围结束时处理对象。(不过该对象必须实现了IDisposable接口)。其功能和try ,catch,Finally完全相同。
比如:
- using (SqlConnection cn = new SqlConnection(SqlConnectionString)){......}//数据库连接
- using (SqlDataReader dr = db.GetDataReader(sql)){......}//DataReader
- PS:这里SqlConnection和SqlDataReader对象都默认实现了IDisposable接口,如果是自己写的类,那就要自己手动来实现IDisposable接口。比如:
- using (Employee emp = new Employee(userCode))
- {
- ......
- }
- Emlpoyee.cs类:
- public class Employee:IDisposable
- {
- 实现IDisposable接口#region 实现IDisposable接口
- /**////
- /// 通过实现IDisposable接口释放资源
- ///
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
- /**////
- /// 释放资源实现
- ///
- ///
- protected virtual void Dispose(bool disposing)
- {
- if (!m_disposed)
- {
- if (disposing)
- {
- // Release managed resources
- if(db!=null)
- this.db.Dispose();
- if(dt!=null)
- this.dt.Dispose();
- this._CurrentPosition = null;
- this._Department = null;
- this._EmployeeCode = null;
- }
- // Release unmanaged resources
- m_disposed = true;
- }
- }
- /**////
- /// 析构函数
- ///
- ~Employee()
- {
- Dispose(false);
- }
- private bool m_disposed;
- #endregion
- }
使用using语句需要注意的几点:
3.1、对象必须实现IDisposeable接口,这个已经说过,如果没有实现编译器会报错误。
如:
- using( string strMsg = "My Test" )
- {
- Debug.WriteLine( strMsg );//Can't be compiled
- }
3.2、第二个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() );
3.3、当同时需要释放多个资源时候,并且对象类型不同,可以这样写:
- using( SqlConnection sqlConn = new SqlConnection( yourConnectionString ) )
- using( SqlCommand sqlComm = new SqlCommand( yourQueryString, sqlConn ) )
- {
- sqlConn.Open();//Open connection
- //Operate DB here using "sqlConn"
- sqlConn.Close();//Close connection
- }
如果对象类型相同,可以写到一起:
- using (Font MyFont = new Font("Arial", 10.0f), MyFont2 = new Font("Arial", 10.0f))
- // use MyFont and MyFont2
- } // compiler will call Dispose on MyFont and MyFont2
3.4、using关键字只是针对C#语句,对于VB等其他语言还没有对应的功能。
关于.Net资源释放问题,也就是对于非内存的资源,最好使用IDisposable接口提供的Dispose来释放。
很明显,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”对象。同时在这里多谢 lmtz 网友对文章提出的异议,从而使我重新审查此文,并进行修正。)
但是对于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();
- }
为了及早释放对象所占用的非托管资源,因此要保证Dispose方法能在使用完对象后被调用,.Net提供了using程序块和try-finally程序块两个方法,两者并没有太大的区别,可能使用using能使程序看得比较简明,但是为了防止异常,需要在using中加入try-catch,这样反而不如try-finally看得舒服,不过这也只是我个人的看法。总的来说,只要把方法合理整合到应用程序当中才是最重要的。
- public DataSet GetRoleList()
- {
- using(DataSet roles=RunProcedure("sp_Accounts_GetAllRoles",new IDataParameter[]{},"Roles"))
- {
- return roles;
- }
- }
using 的作用我记得是这样的。using后面的括号表示这里面有重要的资源产生,using下面的 {}表示在这段代码运行完后释放掉那个