深入理解using

Using 的多重身份
1:引入命名空间
2:创建别名
3:强制资源清理
(一)引入命名空间
存在的误区:
    using类似于Java语言的import指令,都是引入命名空间(Java中称作包)这种逻辑结构;而不同于C语言中的#include指令,用于引入实际的类库。
    using引入命名空间,并不等于编译器编译时加载该命名空间所在的程序集,程序集的加载决定于程序中对该程序集是否存在调用操作,如果代码中不存在任何调用操作则编译器将不会加载using引入命名空间所在程序集。因此,在源文件开头,引入多个命名空间,并非加载多个程序集,不会造成“过度引用”的弊端 。
(二)创建别名
使用using创建别名的用法规则是:Using MyName = namespace | type;其中namespace表示创建命名空间的别名;而type表示创建类型别名。
例子:
    为命名空间创建别名
    using mySpace = LyMIT.myCIS.CommonClass;
    为类型创建别名
    using MyConsole = System.Console;
    MyConsole.WriteLine("应用了类的别名。");
      创建别名的另一个重要的原因在于同一cs文件中引入的不同命名空间中包括了相同名称的类型,为了避免出现名称冲突可以通过设定别名来解决。
以using创建别名,解决了这种可能的命名冲突,当然也可以通过类型全名称来加以区分。
namespace WindowsApplication1
{
    using OneClass = ClassLibrary1.Class1;
    using TwoClass = ClassLibrary2.Class1;
    public partial class Form1 : Form
    {

        public Form1()
        {
            InitializeComponent();
        }
        private void Form1_Click(object sender, EventArgs e)
        {
            MessageBox.Show(OneClass.ShowClassInfo);
            MessageBox.Show(TwoClass.ShowClassInfo);
        }
    }
}
(三)资源清理
由来:
    要理解清楚使用using语句强制清理资源,就首先从了解Dispose模式说起,而要了解Dispose模式,则应首先了解.NET的垃圾回收机制。 .NET提供了Dispose模式来实现显式释放和关闭对象的能力。
Dispose模式
     Dispose模式是.NET提供的一种显式清理对象资源的约定方式,用于在.NET 中释放对象封装的非托管资源。因为非托管资源不受GC控制,对象必须调用自己的Dispose()方法来释放,这就是所谓的Dispose模式。从概念角度来看,Dispose模式就是一种强制资源清理所要遵守的约定;从实现角度来看,Dispose模式就是让要一个类型实现IDisposable接口,从而使得该类型提供一个公有的Dispose方法。

  • using语句提供了强制清理对象资源的便捷操作方式,允许指定何时释放对象的资源源。
  • 所有拥有非托管资源的类型都会实现Idisposable接口,如果我们忘记Dispose()方法,其中的非内存资源会在随后终结器执行时释放,这样对象在内存中存放的时间就比较长,应用程序对资源的清理比较慢。
  • C#中的using语句可以Dispose()方法被调用,我们可以在using语句中分配一个对象,C#编译器会为每一个对象自动产生一个try/finally块。
  • 下面的两端代码将生成一样的IL代码。

            string connStr = string.Empty;
            SqlConnection conn = null;
            //using 语句示例
            using (SqlConnection conn = new SqlConnection(connStr))
            {
                conn.Open();
            }
            //try/finally块
            try
            {
                conn = new SqlConnection(connStr);
                conn.Open();
            }
            finally
            {
                conn.Dispose();
            }
误区:
      (1)对没有实现Idisposable()接口的对象使用using语句。
例子:

//object对象没有实现Idisposeable接口
Using (object obj = Factory.CreateResource())
{
    Console.WriteLine(obj.ToString());
}
//修正版本
Object obj=Factory.CreateResource();
Using (obj as Idsposeable)
{
    Console.WriteLine(obj.ToString());
}
      如果没有实现Idisopose接口,在上面的情况下,using语句退化为using(null),这种做法非常的安全,只是不会做任何的事情。
(2) 潜在的资源泄漏
SqlConnection conn=new SqlConnection(connStr);
SqlCommand cmd=new SqlCommand(cmdStr,conn);
Using(conn as IDisposeable)
Using (cmd as Idisposeable)
{
    conn.Open();
    cmd.ExecuteNonQuery();
}
       确保任何实现了Idisposeable()接口的对象都在using和Try块中分配,否则有可能出现内存泄漏。
     一个方法中有多个需要释放的资源的对象时,可以创建多个using块,或者自己写一个try/finally块,两种方法是等效的,产生的IL代码是完全一样的。
有些对象既实现了Dispose()又实现了Close()。
     Dispose()除了释放资源外,还会通知垃圾回收器这个对象不再需要终结操作。Dispose()通过GC.SuppressFinaize()方法来实现这一点,Close()一般不会这么做。因此调用过Close()的对象仍然留在终结队列中,Dispose()不会将对象从内存中删除,它只是让对象释放非托管资源。
posted on 2009-03-11 10:07  noviceliu  阅读(713)  评论(2编辑  收藏  举报