我写了一个课程如下。我写过它考虑到它主要用于网络(即它将从aspx页面使用)。
public class TestHelper
{
public TestHelper()
{
HttpContext ctxt = HttpContext.Current;
IHttpHandler RequestHandler = ctxt.Handler;
Page CurrentPage;
CurrentPage = (Page)RequestHandler;
CurrentPage.Unload += new EventHandler(CurrentPage_Unload);
Debug.Print("Open all connection here...");
}
void CurrentPage_Unload(object sender, EventArgs e)
{
Debug.Print("Close all connection here...");
}
}
我已经把我的aspx页面代码写成了这样的代码:
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
TestHelper helper = new TestHelper();
helper = null;
}
}
尽管将帮助器分配给'null'但我发现CurrentPage_Unload()
被执行了。为什么会出现这种情况?通常所说的这种行为是什么?
我之所以用这种风格编写类是因为我认为我可以在课堂上以中心方式管理我的数据库连接。通常人们会在后面的aspx代码中调用对象上的方法,如helper.IsValid()
,后跟helper.ProfileExists()
。这些方法中的每一个都有自己的数据库连接对象(IDbConnection),以及它们对应的Open()
& Close()
调用打开/关闭数据库连接。我只觉得我们应该只在代码中执行一次。因此,我使用构造函数打开数据库连接,并使用Page对象的unload事件来关闭连接对象。以这种方式写课是否有任何陷阱?
答案 0 :(得分:4)
正在发生的事情是您将委托附加到页面的Unload事件。即使您的变量设置为null,您的页面仍然存在,并且仍然有一个Unload事件仍然保存对您添加到其中的委托的引用。
要删除委托,您需要使用-=
语法。
CurrentPage.Unload -= new EventHandler(CurrentPage_Unload);
答案 1 :(得分:2)
将null
分配给变量并不会结束其实际生命周期。因为.NET使用非确定性垃圾收集系统(根据几个标准定期清除对象,而不是一旦它们超出范围),就不能依赖于收集的对象在创建它的过程结束之前。
此外,因为您将事件处理程序(意味着委托,其中包含对新构造的实例的引用)附加到另一个对象,所以您将扩展对象的可行生命周期同样。只要附加了该事件处理程序,就无法收集您的对象,直到它所附加的对象符合条件。
答案 2 :(得分:0)
你必须考虑执行行
时会发生什么helper = null;
您只需要引用一个对象。将该对象指定为null时,只需将引用设置为null即可。对象没有发生任何事情。请考虑以下代码:
var first = new object();
second = first;
first = null;
第二个现在是否为空?您可以将引用视为一个数字 - 它只是内存中对象的地址。
.NET垃圾收集器只是查看对象并检查是否有对该对象的引用。如果没有,它将删除该对象。