Tom*_*len 6 c# garbage-collection
在代码中,我们说:
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();
}
Run Code Online (Sandbox Code Playgroud)
这cn.close在技术上是不必要的,因为垃圾收集将为我们处理连接.
但是,我总是喜欢关闭它,不依赖于垃圾收集.这不好吗?浪费时间?或者考虑不依赖自动化的良好做法?
提前感谢您的想法和意见.我将此标记为社区维基,因为它可能是主观的.
Chr*_*ich 15
你永远不应该依赖GC.Raymond Chen 关于此的博客文章是一个很好的起点.从本质上讲,如果你没有手动Close/ Dispose您的连接,那么就不能保证它会发生,因为否则只会不会发生时,Dispose从被称为Finalizer这可能不是不会发生:
正确编写的程序不能假定终结器将在程序终止之前的任何时刻运行.
是的,在实践中,您的连接的终结器可能最终会发生,但即使这样,您仍然保持实时连接的时间超过实际需要的时间.如果数据库在任何时候仅允许有限数量的实时连接,则会产生问题.
你正在做的事情被认为是一种好的做法:当你完成资源时,将它们释放出来.如果一个物体是IDisposable,Dispose当你可以的时候.
首先 - 在您的示例中,您使用的是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();
}
Run Code Online (Sandbox Code Playgroud)
由于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.
Run Code Online (Sandbox Code Playgroud)
在这种情况下,GC将关闭打开的连接并将其返回池中.在这种情况下,这意味着你无法预测何时发生.在实践中,这段代码(很有可能)会泄漏SqlConnections,很快就会耗尽它们(你会得到一个TimeoutException,因为池中没有可用的连接).
所以,是的,你上面的例子是正确的方法.每当您使用某个实现的对象时IDisposable,将其包装在一个using块中.你不需要打扰.Close(),虽然它也没有伤害.我个人不写它.更少的代码,更少的混乱.