コード分析警告CA1063をトリガーするコードがいくつかあります。
CA1063:Microsoft.Design:「Functionality」によって実装されたインターフェースのリストからIDisposableを削除し、代わりに基本クラスのDispose実装をオーバーライドします。
ただし、この警告を修正するために何をする必要があるのかわかりません。
簡単に言うと、IFunctionality
から派生したインターフェースIDisposable
があります。クラスFunctionality
はIFunctionality
を実装しますが、somコードを再利用できるようにクラスReusable
から派生します。クラスReusable
もIDisposable
から派生します。
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
}
Dispose
でFunctionality
をオーバーライドし、基本クラスDispose
を呼び出すことで警告を取り除くことができますが、そうしてもコードのセマンティクスは変更されません。
それで、私が見落としたこの文脈でのIDisposable
について何かありますか、それともこの特定の構成に対して失火するのはCA1063だけですか?
CA1063を抑制できることは知っていますが、ルールは非常に広く、このルールによって報告されるIDisposable
を実装する際の他の問題を見逃したくありません。
これは、ルール自体のマイナーなバグによる誤検知です。クラスが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
{
...
}
また、真剣に検討することをお勧めします ファイナライザーを取り除く ...
IDisposableを再度実装する派生クラスの場合、ここでの「回避策」は正しいパターンです。
しかし、IFunctionality : IDisposable
のデザインを再考する必要があると思います。使い捨てであることは本当にIFunctionality
の懸念ですか?決定は実装クラスに属すると思います。
これは、インターフェース自体ではなく、IDisposable
の使用に関連しています。保護されたDispose(bool)
メソッドを提供してオーバーライドすることにより、その使用に推奨されるパターンを実装しているだけです。これはインターフェイス自体の一部ではありません。
オーバーライドメソッドが実際に何も追加しない場合は、それを省略しても問題ありません。警告CA1063は問題を強調するためにありますが、実際に処理するリソースがないことがわかっている場合は、空の実装を提供するか、この特定のルールを除外することで回避できます。ファイル。
これは [SuppressMessage]
属性。