2012-01-09 159 views
1

我有几个静态方法将窗体转换为控件(如下所示)。分析器标记两个,声明:“CA2000:Microsoft.Reliability:在方法'...'中,对象'form'不是沿着所有异常路径处理的。在所有引用之前调用System.IDisposable.Dispose对象'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; 
    } 

    ... 
} 

回答

6

CA2000麻烦,太多的虚假警告。 FxCop不够聪明,无法知道Control类是如何工作的。它的Dispose()方法在后创建了一个有用的。只有这样才会有可以处置的非托管资源。但是,直到您返回的TabPage被添加到TabControl并且该控件反过来被添加到窗体并调用该窗体的Show()方法之后,才会发生这种情况。我们看不到的代码(对于这个问题也没有FxCop)。此外,他们实际上得到处置,即使有一个例外,当本地窗口被破坏。

您可以通过向方法添加try/catch来禁止警告,以便您可以在catch块中调用Dispose()。但这是一个错误,它只是增加了不必要的代码,在运行时没有任何用处。使用[SuppressMessage]属性摆脱警告。

+0

“[SuppressMessage(”Microsoft.Reliability“,”CA2000“)]”像魅力一样工作。非常感谢你。 – jww 2012-01-10 18:34:38

1

根据您的代码,您应该能够安全地忽略该警告。

0

捕捉异常,调用Dispose,扔?

2

根据你的代码,不仅应该你忽略了警告,但你必须忽略警告。

一个幼稚的做法是

public Control FormAsControl() 
{ 
    using (Form form = new Foo()) 
    { 
     // Set properties 
     return form; 
    } 
} 

但随后form将之前调用者可以使用它处理完毕!

请注意,我假设你的意思Foo类从Form派生,而你的意思是FormAsControl返回Control,不Form

+0

同意。谢谢约翰。 – jww 2012-01-10 18:40:02

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(); 
     } 
    } 

    // ... 
} 

这样,如果任何财产分配导致异常,该对象是否仍然适当处理。