2010-08-23 26 views
6

在代碼中,說我們有:垃圾收集,我們應該依靠它嗎?

using (SqlConnection cn = new SqlConnection(ConfigurationManager.ConnectionStrings["LocalSqlServer"].ToString())) 
{ 
    cn.Open(); 

    // Set all previous settings to inactive 
    using (SqlCommand cmd = new SqlCommand("UPDATE tblSiteSettings SET isActive = 0", cn)) 
    {        
     cmd.ExecuteNonQuery(); 
    } 

    cn.Close(); 
} 

cn.close在技術上並不需要作爲垃圾回收將採取我們的連接服務。

但是,我總是喜歡關閉它,而不是依靠垃圾收集。這不好嗎?浪費時間?還是認爲不要依靠自動化的好做法?

感謝您提前提出您的想法和意見。我會將其標記爲社區wiki,因爲它可能是主觀的。

+7

由於您使用'using'語句,'cn.Close()'完全是多餘的。在您的示例中爲 – 2010-08-23 09:03:14

+4

,它是IDispose/using()誰清除連接,而不是GC。控制連接和文件等資源的生命週期是很好的(基本)練習。 GC應該僅用於內存資源。 – tenfour 2010-08-23 09:08:32

回答

14

你不應該依賴於GC。 Raymond Chen的blog article about this是一個很好的起點。事實上,如果你沒有手動您的連接Close/Dispose做,那麼就不能保證它會發生,因爲否則永遠只能發生在Dispose由這可能不是不會發生的Finalizer叫:

正確編寫的程序不能 假定終結器將在程序 終止之前的任何時刻運行 。

是的,實際上,連接的終結器可能最終會發生,但即使如此,您仍然堅持實時連接的時間超過您實際需要的時間。如果數據庫在任何時候只允許有限數量的實時連接,這可能會產生問題。

你在做什麼被認爲是良好的做法:當你完成資源,釋放它們。如果一個對象是IDisposable,Dispose就可以了。

+0

+1。特別是關於數據庫連接,幾個月前,我被一個同事的代碼咬了一口。他只是把所有清理工作都留給了終結者,這對於小數據庫來說工作得很好,但由於在退出過程中終結者的時間限制,「突然」開始在大型數據庫上失敗。更多細節在這裏:http://nitoprograms.blogspot.com/2009/08/finalizers-at-process-exit.html – 2010-08-23 14:15:32

+0

請注意,陳繼續說,終結者不能保證**永遠**被稱爲,甚至當應用程序退出時。 – Tergiver 2010-08-23 14:52:55

6

首先 - 在您的示例中,您使用的接口是IDisposable,與GC完全無關。從本質上講,你的代碼編譯成這樣:

SqlConnection cn = null; 
try 
{ 
    cn = new SqlConnection(ConfigurationManager.ConnectionStrings["LocalSqlServer"].ToString()); 
    cn.Open(); 

    // Set all previous settings to inactive 
    using (SqlCommand cmd = new SqlCommand("UPDATE tblSiteSettings SET isActive = 0", cn)) 
    { 
     cmd.ExecuteNonQuery(); 
    } 
    cn.Close(); 
} 
finally 
{ 
    if (cn != null) 
     cn.Dispose(); 
} 

由於cn.Dispose()cn.Close()在這種情況下是相同的 - 是的,後者是多餘的。

現在,如果你想談論GC,那麼你會寫這樣的:

SqlCOnnection cn = new SqlConnection(ConfigurationManager.ConnectionStrings["LocalSqlServer"].ToString()); 
    cn.Open(); 

    // Set all previous settings to inactive 
    using (SqlCommand cmd = new SqlCommand("UPDATE tblSiteSettings SET isActive = 0", cn)) 
    { 
     cmd.ExecuteNonQuery(); 
    } 
    cn = null; // Or just leave scope without doing anything else with cn. 

在這種情況下,它會採取GC關閉打開的連接,並將其返回到池中。在這種情況下,這意味着你無法預測何時發生。實際上,這個代碼會(很有可能)泄漏SqlConnections,很快你會用完它們(你會得到一個TimeoutException,因爲池中沒有可用的連接)。

所以,是的,你上面的例子是正確的方法。無論何時使用實現IDisposable的某個對象,將其包裝在using塊中。你不需要打擾.Close(),雖然它也沒有傷害。我個人不寫。更少的代碼,更少的混亂。