簡體   English   中英

VS2010代碼分析期間的IDisposable和CA2000警告

[英]IDisposable and CA2000 warning during VS2010 Code Analysis

我在這里需要一些建議,我希望有人可以幫助我。 我有以下 class 結構(簡化):

public class Bar: IDisposable {...}

public abstract class FooBase: IDisposable
{
    Bar bar;
    bool disposed;

    internal FooBase(Bar bar)
    {
        this.bar=bar;
    }

    public void Dispose()
    {
         Dispose(true);
         GC.SupressFinalize(this);

    }

    protected void Dispose(bool disposing)
    {
         if (!this.disposed)
         {
             if (disposing)
             {
                 this.bar.Dispose();
             }

             this.disposed = true;
         }
    }
}

public FooA: Foo {...}
public FooB: Foo {...}

public static class FooProvider
{
    public static FooA GetFooA()
    {
       Bar bar = new Bar();
       ...
       return new FooA(bar);
    }

    public static FooB GetFooB()
    {
        Bar bar = new Bar();
        ...
        return new FooB(bar);
    }

    ...
}

當我對此運行代碼分析時,我在 FooProvider class 的所有“CreateFooX()”方法上收到警告 CA2000。 此警告提供以下消息:

“微軟。可靠性:在方法 'FooProvider.GetFooX()' 中,在 scope 的所有引用之前調用 object 'bar' 上的 System.IDisposable.Dispose。”

Microsoft 建議永遠不要抑制此警告,但我不確定它是否會警告代碼中的實際問題。 確實,在我們考慮的任何 'CreateFooX()' 方法中,在離開 scope 之前,'bar' 都不會被處理,但對它的引用仍然存在於 'FooX' object 中,最終將被處理並反過來處理處理 '酒吧'。

我是否對 Dispose 模式的工作方式理解有誤,並且我的代碼中有一些根本缺陷,還是應該直接取消此警告?

編輯

由於一些評論,我嘗試將工廠方法修改為以下內容:

public static class FooProvider
{
    public static FooA GetFooA()
    {
       Bar bar = null;

       try
       {
           bar =  new Bar();
           ...
           return new FooA(bar);
       }
       catch
       {
           if (bar != null) bar.Dispose();
           throw;
       }
    }

    ...
}

但我仍然收到同樣的警告。 我想這只是一個誤報,我可以安全地接受它。

感謝您的任何建議。

這是代碼分析部分的典型誤報。 它真的無法理解你的代碼的內在情況,所以它給出了一個普遍的答案。 請謹慎行事,但只要您確認您有誤報,您就可以放心地忽略它。

這不是誤報。 如果在創建Bar之后但在將其傳遞給Foo構造函數之前拋出異常怎么辦? 我看到幾個代碼路徑可能不會處理一個或多個對象。

你的一次性模式對我來說似乎有點不對勁。 我認為您不應該在 FooBase class 中調用 bar.Dispose。 為了您正在處理的對象的安全,並且能夠多次安全地調用 Dispose,我會推薦這種方法。

  private bool _disposed;
  public void Dispose()
  {
     Dispose( true );
     GC.SuppressFinalize( this );
  }

  protected virtual void Dispose( bool disposing )
  {
     if ( disposing )
     {
        if ( !_disposed )
        {
           if ( Bar != null )
           {
              Bar.Dispose();
           }

           _disposed = true;
        }
     }
  }

至於錯誤,我認為這應該照顧到 static 分析警告。 我在一個測試項目中按如下方式實現了您的代碼,啟用了所有 static 分析警告,而沒有出現警告問題。

public class Bar : IDisposable
{
  private bool _disposed;
  public void Dispose()
  {
     Dispose( true );
     GC.SuppressFinalize( this );
  }

  protected virtual void Dispose( bool disposing )
  {
     if ( disposing )
     {
        if ( !_disposed )
        {
           _disposed = true;
        }
     }
  }
}

public abstract class FooBase : IDisposable
{
  public Bar Bar
  {
     get;
     set;
  }

  internal FooBase( Bar bar )
  {
     Bar = bar;
  }

  private bool _disposed;
  public void Dispose()
  {
     Dispose( true );
     GC.SuppressFinalize( this );
  }

  protected virtual void Dispose( bool disposing )
  {
     if ( disposing )
     {
        if ( !_disposed )
        {
           if ( Bar != null )
           {
              Bar.Dispose();
           }

           _disposed = true;
        }
     }
  }
}

public class FooA : FooBase
{
  public FooA( Bar bar )
     : base( bar )
  {
  }
}

public static class FooProvider
{
  public static FooA GetFooA()
  {
     Bar bar;
     using ( bar = new Bar() )
     {
        return new FooA( bar );
     }
  }
}

[TestClass]
public class UnitTest1
{
  [TestMethod]
  public void StaticAnalysisTest()
  {
     Assert.IsNotNull( FooProvider.GetFooA().Bar );
  }
}

我希望這是有幫助的。

至少這個問題的一部分並不是真正的誤報,即使它不一定是一個非常有用的問題檢測。 要解決您編輯版本的剩余問題,您需要在bar分配之后立即打開try塊,而不是在它之前。 例如

Bar bar = new Bar();
try
{
    ///...            
    return new FooA(bar);
}
catch
{
    bar.Dispose();
    throw;
}

不幸的是,在您進行此更改后,您仍然會遇到 CA2000 違規,這可能是誤報。 這是因為該規則不會檢查您是否將bar放入新創建的 FooA 的FooA中。 如果它進入 FooA 中的FooA ,您可以安全地為違規創建抑制。 但是,如果它沒有進入 FooA 中的FooA ,則應將其放置在finally子句而不是catch子句中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM