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()不會將對象從記憶體中刪除,它只是讓對象釋放非託管資源。