首页 新闻 会员 周边 捐助

关于对象生命周期的一个小问题

0
悬赏园豆:5 [已解决问题] 解决于 2008-04-22 16:19
<P>大家好。如下面的代码:</P> <P>public class Test {<BR>&nbsp;&nbsp;&nbsp; public void Method() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SqlConnection conn = new SqlConnection(connStr);&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //...方法体中没有显式关闭conn<BR>&nbsp;&nbsp;&nbsp; }<BR>}</P> <P>对于这里的conn,我的理解是:调用Method()方法时,当执行到方法的最后一个}时,conn变量的作用域已到,所以栈上的conn变量值被释放,但是托管堆中的conn对象仍然存在,它要等待垃圾回收器的清理,这样说对么?</P> <P>所以如果要在此返回一个SqlDataReader对象的话,必须要cmd.ExecuteReader(CommandBehavior.CloseConnection),因为这么做的话,当返回的DataReader对象在另外的地方被关闭时,这个conn也自动被关闭了,对么?</P>
水言木的主页 水言木 | 小虾三级 | 园豆:586
提问于:2008-04-22 12:55
< >
分享
最佳答案
0
严格的说法是: 调用堆栈是GC的根对象,而这个例子中的调用堆栈中包含到Connection的引用(而不是Connection对象,如果你要理解这里的策略,一定要很好的理解引用和对象的区别),因此,在这个方法中,如果触发了GC的回收动作,GC不会回收Connection对象。 同时,Connection对象应该实现了Disposable模式(或者继承自SafeHandle),在Finalize方法中调用了自己的Close方法。 因此,如果你不显示的调用Connection的Close方法或Dispose方法时,它将会被GC的Finalize线程回收。这种回收是不可靠的,并且可能产生性能问题,因此,建议你使用楼上的写法。 另外,SqlDataReader关闭时关闭Connection对象的做法,个人感觉是微软.NET目前的机制不能很好的平衡这一点,因此为了照顾易用性,而损失了逻辑严密性的一个做法。建议不要追究它的逻辑是否严密了。你就认为这时候,Reader的Close方法在调用它自己抓着的Connection对象上的Close方法就可以了。
Colin Han | 老鸟四级 |园豆:3041 | 2008-04-22 13:25
其他回答(2)
0
对。
deerchao | 园豆:8367 (大侠五级) | 2008-04-22 13:01
0
using(SqlConnection conn = new SqlConnection(_connectionString)){ PrepareCommand(cmd, conn, null, cmdType, cmdText, cmdParms); int val = cmd.ExecuteNonQuery(); cmd.Parameters.Clear(); return val; } 你说的第一点 我想应该是这样的吧! 但是后面说的就有点问题了
yeyang | 园豆:418 (菜鸟二级) | 2008-04-22 13:03
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册