代码之家  ›  专栏  ›  技术社区  ›  deostroll

解释为什么对象的生存期超出范围

  •  2
  • deostroll  · 技术社区  · 14 年前

    我写了一节课如下。我写这篇文章的时候考虑到它主要是在web上使用的(也就是说,它将从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;
        }
    
    }
    

    尽管将helper赋值为'null',我发现 CurrentPage_Unload() 被执行。为什么这种行为如此?这种行为通常叫什么?

    helper.IsValid() 然后 helper.ProfileExists() 在aspx代码后面。这些方法中的每一个都有自己的db connection对象(IDbConnection)及其相应的 Open() & Close() 调用打开/关闭数据库连接。我只是觉得我们应该在代码中只做一次。因此,我使用构造函数打开db连接,使用Page对象的unload事件关闭连接对象。这样写课程有什么陷阱吗?

    3 回复  |  直到 14 年前
        1
  •  2
  •   Adam Robinson    14 年前

    分配 null 对一个变量的访问不会结束它的实际生存期。因为.NET使用了一个不确定的垃圾收集系统(在这个系统中,对象是根据几个条件定期清除的,而不是在对象超出范围后立即清除),所以您不能依赖对象 在创建它的进程结束之前被收集。

    此外,由于要将事件处理程序(意味着委托,其中包含对新构造实例的引用)附加到另一个对象,因此要扩展 可行的 你的物体的寿命也一样。只要附加了该事件处理程序,就无法收集对象,直到它附加到的对象符合条件为止。

        2
  •  4
  •   Greg B    14 年前

    所发生的事情是将委托附加到页面的Unload事件。即使将变量设置为null,页面仍然存在,并且仍然有一个Unload事件,该事件仍然保存对添加到其中的委托的引用。

    要删除代理,您需要使用 -= 语法。

    CurrentPage.Unload -= new EventHandler(CurrentPage_Unload); 
    
        3
  •  0
  •   Jaco Pretorius    14 年前

    helper = null;
    

    您只需要引用一个对象。当您将该对象指定为null时,您只需将引用设置为null。物体什么也没发生。考虑以下代码:

    var first = new object();
    second = first;
    
    first = null;
    

    秒现在是空的吗?你可以把一个引用看作一个简单的数字——它只是内存中对象的地址。