我再次运行静态分析检查,我在
上得到了100多个唠叨Label foo = new Label(); //Where this is an ASP.NET web forms label
我是否需要在这些网络表单标签上调用dispose?另外,页面生命周期的后期是否可以安全地调用Dispose?如果一个类实现了IDisposable,但实际上没有做任何事情,那么不调用dispose会有什么危害吗?
(是的,我已经读过关闭连接是一件好事,使用块也是一件好事。)
DataSet是另一个似乎因为莫名其妙的原因而实现IDisposable的类。
答案 0 :(得分:6)
实际上,您无需在添加到父网页的网络表单控件上调用Dispose()
。我也看到了这些警告,并试图弄清楚如何处理它们,然后在using
语句中包装所有控件创建之前,我测试了是否实际调用了一个已添加到父级的控件上的dispose
TestDispose.ascx.cs:
public partial class TestDispose : System.Web.UI.UserControl {
public void override Dispose() {
// Set breakpoint here
base.Dispose();
}
}
TestPage.aspx.cs:
public partial class TestPage : System.Web.UI.Page {
public void override OnInit() {
// test will be disposed of when the page is destroyed
TestDispose test = new TestDispose();
test.ID = "TestDispose";
this.Controls.Add(test);
// test1 will not be disposed of because it was not added
// to the page's control tree.
TestDispose test1 = new TestDispose();
test1.ID = "TestDispose1";
}
}
如果在调试器中使用TestDispose.Dispose()
上的断点运行此操作,您将发现父页面在页面被销毁时调用Dispose()
。一旦我确定了这一点,我就开始添加排除项,并在页面控制树中的对象上调用“Dispose()
”。
困扰我的一件事是我无法在任何地方找到它。虽然ASP.Net Page Lifecycle是一个很好的资源,但它没有提到在子控件上调用Dispose()
。
然而,使用Reflector,我能够确定通过以下层次结构调用Dispose()
:
System.Web.UI.Page.AspCompatBeginProcessRequest
-> System.Web.UI.Page.ProcessRequest
-> System.Web.UI.Page.ProcessRequestCleanup
-> System.Web.UI.Control.UnloadRecursive
System.Web.UI.Control.UnloadRecursive
将遍历每个Controls属性,并最终为每个Control对象调用Dispose()
。任何继承自System.Web.UI.UserControl
的对象都会实现IDisposable
。
所以,遗憾的是,如果没有实际的文档,我们目前依赖的是实现细节,而不是合同。虽然我不会因此而改变我的排除/理由,但我只是想为这个答案的其他读者揭示这一点。
答案 1 :(得分:3)
如果一个类实现了IDisposable,但实际上没有做任何事情,那么不调用dispose会有什么害处吗?
如果班级没有做任何事情,那么不调用dispose是没有害处的。但是,您正在假设a)实现不会改变,b)没有任何子类化
DataSet是另一个似乎因莫名其妙的原因实现IDisposable的类
关于DataSet本身的主题,有a question here on Stack Overflow得出结论,处理它会加速内存清理,因为它是MarshalByValueComponent。
我认为一个好的经验法则是:如果你知道实现没有做任何事情并且很容易处理,那么处理它,但不要忘记你的方式(比如设置Page.Unload事件)处理者)去做。但是,如果您知道它释放非托管资源,总是处理它,除非文档另有说明(ala SharePoint)。
答案 2 :(得分:1)
你必须仔细看看课程。如果它只是一个无害的Dispose(),那么你可以忽略它。有几个类因为它们的基类而拥有它。
反对这种推理的主要论点是:它可能会在未来的版本中发生变化。但不太可能是Label。
但要小心,如果类(或其基类)实现完整的Disposable模式,它也可能有一个析构函数(Finalizer)。然后非常需要Dispose()来取消终结器。不这样做会严重损失性能。
答案 3 :(得分:0)
是的,如果Dispose()方法没有做任何事情,那么不调用Dispose将是无害的。如果您的静态分析工具实际上正在使用这些工具,那么如果您计划使用Winforms,则应该将其关闭。 IMO,这不是一个好的分析,因为有很多场景已知Dispose()被链接,只有根调用是必要的(即流/读者)。