web-dev-qa-db-ja.com

コード分​​析CA1063は、IDisposableから派生し、基本クラスで実装を提供するときに起動します

コード分​​析警告CA1063をトリガーするコードがいくつかあります。

CA1063:Microsoft.Design:「Functionality」によって実装されたインターフェースのリストからIDisposableを削除し、代わりに基本クラスのDispose実装をオーバーライドします。

ただし、この警告を修正するために何をする必要があるのか​​わかりません。

簡単に言うと、IFunctionalityから派生したインターフェースIDisposableがあります。クラスFunctionalityIFunctionalityを実装しますが、somコードを再利用できるようにクラスReusableから派生します。クラスReusableIDisposableから派生します。

public class Reusable : IDisposable {

  ~Reusable() {
    Dispose(false);
  }

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

  protected virtual void Dispose(Boolean disposing) {
    // ...
  }

  public void DoSomething() {
    // ...
  }

}

public interface IFunctionality : IDisposable {

  void DoSomething();

  void DoSomethingElse();

}

public class Functionality : Reusable, IFunctionality {

  public void DoSomethingElse() {
    // ...
  }

#if WORK_AROUND_CA1063
  // Removes CA1063
  protected override void Dispose(Boolean disposing) {
    base.Dispose(disposing);
  }
#endif

}

DisposeFunctionalityをオーバーライドし、基本クラスDisposeを呼び出すことで警告を取り除くことができますが、そうしてもコードのセマンティクスは変更されません。

それで、私が見落としたこの文脈でのIDisposableについて何かありますか、それともこの特定の構成に対して失火するのはCA1063だけですか?

CA1063を抑制できることは知っていますが、ルールは非常に広く、このルールによって報告されるIDisposableを実装する際の他の問題を見逃したくありません。

38

これは、ルール自体のマイナーなバグによる誤検知です。クラスがIDisposableを再実装するかどうかを判断しようとすると(オーバーライドできる基本クラスの実装があることを確認した後)、クラスのインターフェイスにIDisposableが含まれているかどうかのみが確認されます。残念ながら、アセンブリメタデータに表示されるインターフェイスリストには、クラスが元のC#コードで明示的に実装するインターフェイスを介して継承されたインターフェイスを含む、インターフェイスの「展開された」リストが含まれます。これは、FxCopがFunctionalityクラスに対して次のような宣言を認識していることを意味します。

public class Functionality : Reusable, IFunctionality, IDisposable
{
    ...
}

このメタデータ表現を考えると、ImplementIDisposableCorrectlyルールは、クラスが実際にIDisposableを再実装しているかどうかを判断する方法についてもう少しインテリジェントである必要があります(たとえば、基本クラスにオーバーライド可能なDisposeがある場合は明示的なDispose()実装を探すことによって) (ブール))。ただし、ルールでこれが行われない場合、最善のアプローチは誤検知を抑制することです。

ところで、現在の条件付きコンパイルアプローチの代わりに、誤検知を抑制するために SuppressMessageAttribute を使用することを真剣に検討することをお勧めします。例えば。:

[SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly",
    Justification = "False positive.  IDisposable is inherited via IFunctionality.  See http://stackoverflow.com/questions/8925925/code-analysis-ca1063-fires-when-deriving-from-idisposable-and-providing-implemen for details.")]
public class Functionality : Reusable, IFunctionality
{
    ...
}

また、真剣に検討することをお勧めします ファイナライザーを取り除く ...

40
Nicole Calinoiu

IDisposableを再度実装する派生クラスの場合、ここでの「回避策」は正しいパターンです。

しかし、IFunctionality : IDisposableのデザインを再考する必要があると思います。使い捨てであることは本当にIFunctionalityの懸念ですか?決定は実装クラスに属すると思います。

4
Henk Holterman

これは、インターフェース自体ではなく、IDisposableの使用に関連しています。保護されたDispose(bool)メソッドを提供してオーバーライドすることにより、その使用に推奨されるパターンを実装しているだけです。これはインターフェイス自体の一部ではありません。

オーバーライドメソッドが実際に何も追加しない場合は、それを省略しても問題ありません。警告CA1063は問題を強調するためにありますが、実際に処理するリソースがないことがわかっている場合は、空の実装を提供するか、この特定のルールを除外することで回避できます。ファイル。

これは [SuppressMessage] 属性。

1
David M