有关处理表单的代码分析警告

时间:2012-01-09 20:48:57

标签: c# .net visual-studio-2010 code-analysis

我有几种将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;
  }

  ...
}

5 个答案:

答案 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?