早在C++的日子裏,除了安全是真正重要的事情。如果我沒有記錯的話,Sutter的Exceptional C++對此進行了相當詳細的描述。
現在有一件事可能會讓人覺得奇怪,那就是C++中沒有'finally'。如果您在堆棧中添加創建對象,則在您退出示波器時它將自動「處置」。說穿了,範圍就是'{'和'}'會爲你管理的事情。
如果你在做C#,異常處理仍然很重要,但在不同的層面。在所有情況下,你必須確保你的整體狀態保持一致。那麼這是如何工作的?
using
無非是一個圍繞try
,catch
和finally
的包裝。它基本上在finally
中創建了Dispose
,從而確保當您退出範圍時(無論出於何種原因),該對象被清理(即假設它實現了IDisposable
)。正因爲如此,以確保對象最簡單的方法是正確的清理,是通過:
- 創建一個實例,
- 使用實例,
- 處置實例
(在此爲了)
如:
using (var connection = new Connection()) // create instance
{
// use connection instance here
} // dispose connection instance -> implicitly created by 'using'.
重複使用代碼
如果你不想一遍寫的代碼,這是一件好事(f.ex.使用連接字符串),您可以手動處理對象,也可以使用簡單的回調函數來保持流程相同。
private void Execute(Action<Connection> action)
{
using (var connection = new Connection()) // create instance
{
// use connection instance here
action(connection); // callback; this won't break the described mechanism
} // dispose connection instance -> implicitly created by 'using'.
}
爲什麼不使用using
正確不好
因此,這裏的返回,而不考慮任何使用該連接的實現:
// Buggy connection builder
private Connection CreateConnection()
{
Connection tmp = new Connection();
// do some stuff with tmp, might throw
return tmp;
}
private void Client()
{
using (var connection = CreateConnection())
{
// do something with the connection, assuming we're safe
}
}
這似乎都不錯,還行,但它其實是不正確的。你知道嗎?
在它所說的「用tmp做某些事情」的部分,可能會出錯,導致該方法拋出。發生這種情況時,該對象將永遠不會返回給客戶端,並且保留活動Connection
而無需參考。即使你認爲你很安全,但實際上並不是。
關於構造和異常
如果你注意,這也意味着事情都可能出錯的構造函數。如果你創建了一個物體,如果狗屎撞上了風扇,那麼這個物體沒有被正確清理,你也有一個懸掛的物體。例如:
// Buggy connection wrapper
public class ConnectionWrapper : IDisposable
{
public ConnectionWrapper()
{
this.connection = new Connection();
// do some other stuff, some of which might throw
}
private Connection connection;
// ...
// IDisposable stuff.
}
private void Client()
{
using (var connection = new ConnectionWrapper())
{
// do something with the connection, assuming we're safe
}
}
此外,構造函數中的代碼可能會引發異常。在這種情況下,構造函數不會將對象返回給客戶端,這意味着IDisposable
將不會在using
的finally
中調用。這並不意味着IDisposable
在這裏是錯誤的 - 事實上它不是!
這裏出現的問題是我們創建了一個不返回並且未清理的IDisposable
對象。我們可以通過添加一個catch
來解決這個問題,它在清理連接後簡單地重新拋出異常。
您不應該在這裏使用「使用」:您正在返回無用的連接 –
自從您使用'using'語句後,連接一旦返回就會關閉。但是,我根本不會使用這種方法。使用'using'語句需要的連接。請注意,打開連接並不意味着它將通過[connection-pooling](http://msdn.microsoft.com/zh-cn/library/8xx3tyca(v = vs.110).aspx)進行物理打開,它是隻是標記爲「正在使用」。 –
「返回null」無法訪問 – Jordi