解释为什么对象的生命周期在作用域之外

发布于 2024-09-10 03:56:44 字数 1244 浏览 2 评论 0原文

我写了一个类如下。我编写它时考虑到它主要用于网络(即它将在​​ 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() 被执行。为什么会有这样的行为呢?这种行为一般称为什么?

我以这种风格编写课程的原因是因为我认为我可以在课程中以集中方式最好地管理我的数据库连接。通常人们会在后面的 aspx 代码中调用对象上的方法,例如 helper.IsValid() ,然后调用 helper.ProfileExists() 。每个方法都有自己的数据库连接对象(IDbConnection),以及相应的Open()& Close() 调用打开/关闭数据库连接。我只是觉得我们应该只在代码中执行一次。因此,我使用构造函数来打开数据库连接,并使用 Page 对象的卸载事件来关闭连接对象。以这种方式编写课程有什么陷阱吗?

I've written a class as follows. I've written it taking into consideration that its mainly for use on the web (i.e. it will be used from aspx pages).

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...");
    }
}

And I've written my aspx page's code behind like this:

public partial class _Default : System.Web.UI.Page 
{    
    protected void Page_Load(object sender, EventArgs e)
    {
        TestHelper helper = new TestHelper();
        helper = null;
    }

}

In spite of assigning helper to 'null' I find that CurrentPage_Unload() gets executed. Why is this behaviour so? What is this behaviour generally called?

The reason why I've written the class in that style was because I thought I could best manage my db connections in a central fashion in the class. Usually people would call methods on the object like helper.IsValid() followed by helper.ProfileExists() in the aspx code behind. Each of those methods would have their own db connection objects(IDbConnection), and their corresponding Open() & Close() calls to open/close db connection. I just felt that we should only do this only once in code. Hence I used the constructor to open db connections, and the Page object's unload event to close the connection objects. Are there any pitfalls to writing classes this way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

甜点 2024-09-17 03:56:44

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

要删除委托,您需要使用 -= 语法。

CurrentPage.Unload -= new EventHandler(CurrentPage_Unload); 

What is happening is you're attaching a delegate to the Unload event of the page. Even after your variable has been set to null, your page still exists and still has an Unload event which still holds a reference to the delegate you added to it.

To remove a delegate you need to use -= syntax.

CurrentPage.Unload -= new EventHandler(CurrentPage_Unload); 
酒绊 2024-09-17 03:56:44

null 分配给变量并不会结束其实际生命周期。由于 .NET 使用非确定性垃圾收集系统(其中根据多个条件定期清除对象,而不是在它们超出范围时立即清除),因此您不能依赖对象曾经被收集在创建它的进程结束之前。

此外,因为您将事件处理程序(即委托,其中包括对新构造的实例的引用)附加到另一个对象,所以您也延长了对象的可行生命周期。只要附加了该事件处理程序,您的对象就无法被收集,直到它所附加的对象符合条件为止。

Assigning null to a variable does not end its actual lifetime. Because .NET uses a non-deterministic garbage collection system (where objects are periodically purged based on several criteria, rather than as soon as they fall out of scope), you cannot rely on an object ever being collected before the process that created it ends.

Furthermore, because you're attaching an event handler (meaning a delegate, which includes a reference to your newly-constructed instance) to another object, you're extending the viable lifetime of your object as well. As long as that event handler is attached, your object cannot be collected until the object it's attached to is eligible.

早茶月光 2024-09-17 03:56:44

您必须考虑执行该行时会发生什么

helper = null;

您只是有一个对象的引用。当您将该对象分配为 null 时,您只需将引用设置为 null 即可。该对象没有发生任何事情。考虑以下代码:

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

first = null;

第二个现在是否为空?您可以将引用视为简单的数字 - 它只是内存中对象的地址。

.NET 垃圾收集器只是查看对象并检查是否有对该对象的引用。如果没有,它将删除该对象。

You have to think about what happens when you execute the line

helper = null;

You simply have a reference to an object. When you assign that object to null, you're simply setting your reference to null. Nothing has happened to the object. Consider the following code:

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

first = null;

Would second now be null? You can think of a reference as simply a number - it's simply the address of the object in memory.

The .NET garbage collector simply looks at objects and checks if there are any references to that object. If not, it will remove that object.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文