我有几种将Form转换为Control的静态方法(如下所示)。分析器标记两者,说明“CA2000:Microsoft.Reliability:In method'...',object'form'不是沿着所有异常路径放置的。在所有对它的引用之前调用System.IDisposable.Dispose on object'form'超出了范围。“类似标记为tabPage
。
注意:对于那些没有Enterprise Edition和Analyzer菜单的用户,这看起来很像FxCop输出。
我不清楚我应该做什么。如果new
失败,则会抛出异常。我有机会致电Dispose
?
class Foo
{
static public Form FormAsControl()
{
Form form = new Foo();
form.TopLevel = false;
form.FormBorderStyle = FormBorderStyle.None;
form.Dock = DockStyle.Fill;
form.Visible = true;
return form;
}
static public TabPage FormAsTabPage()
{
Form form = Foo.FormAsControl();
TabPage tabPage = new TabPage();
tabPage.Text = form.Text;
tabPage.Controls.Add(form);
return tabPage;
}
...
}
答案 0 :(得分:6)
CA2000很麻烦,错误警告太多了。 FxCop不够聪明,不知道Control类是如何工作的。它的Dispose()方法只在创建本机控制窗口后执行一些有用的操作。只有这样才会有可以处理的非托管资源。但是,直到您返回的TabPage被添加到TabControl并且该控件依次被添加到表单并且调用该表单的Show()方法时才会发生这种情况。我们无法看到的代码(也不是FxCop)。此外,当本机窗口被破坏时,即使出现异常,它们实际上做也会被处理掉。
您可以通过向方法添加try / catch来禁止警告,以便可以在catch块中调用Dispose()。但这将是一个错误,它只是添加了不必要的代码,在运行时没有做任何有用的事情。使用[SuppressMessage]属性去除警告。
答案 1 :(得分:2)
根据您的代码,不仅应您忽略警告,而必须忽略该警告。
一个天真的实现可能是
public Control FormAsControl()
{
using (Form form = new Foo())
{
// Set properties
return form;
}
}
但在调用者可以使用它之前,form
将被处理掉!
请注意,我假设您要将课程Foo
派生自Form
,并且您的意思是FormAsControl
返回Control
,而不是Form
。
答案 2 :(得分:1)
根据您的代码,您应该能够安全地忽略该警告。
答案 3 :(得分:1)
我们可以在这里学习C ++的RAII技术:
class auto_disposer<C> : IDisposable where C : class
{
public C Child { get; private set; }
public auto_disposer(C c) { Child = c; }
public void Dispose() { IDisposable d = Child as IDisposable; if (d != null) d.Dispose(); }
public C Release() { C retval = Child; Child = null; return retval; }
}
class Foo
{
static public Form FormAsControl()
{
using (var ad = new auto_disposer<Foo>(new Foo())) {
Form form = ad.Child;
form.TopLevel = false;
form.FormBorderStyle = FormBorderStyle.None;
form.Dock = DockStyle.Fill;
form.Visible = true;
return ad.Release();
}
}
// ...
}
这样,如果任何属性赋值导致异常,该对象仍然可以正确处理。
答案 4 :(得分:0)
抓住异常,调用Dispose,throw?