2012-01-19 30 views
31

Iはコード分析警告CA1063トリガするいくつかのコードを有する:コード分析CA1063火災

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

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

簡単に言えば、私はIDisposableから派生したインターフェイスIFunctionalityを持っています。クラス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 

} 

私はFunctionalityDisposeをオーバーライドし、そのコードの意味を変更しないでくださいやっていても、基本クラスDisposeを呼び出すことによって、警告を取り除くことができます。

この文脈ではIDisposableについて何かありますか?見落としてしまったのですか、この特定の構造に対して失礼になったのはCA1063ですか?

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

+0

古い問題を検討する必要がありますが、CA1063の問題がsealed' 'としてクラスをマークすることによって克服何回もあります。クラスが ''封印されていない場合、クラスは 'virual'または/および' Dispose() 'メソッドを' protected'にしなければならないと思います。 – mortb

答えて

34

これは、ルール自体のマイナーなバグのために偽陽性です。クラスがIDisposableを再実装するかどうかを判断しようとすると(オーバーライド可能な基本クラスの実装があることがわかった後)、クラスのインタフェースにIDisposableが含まれているかどうかを調べます。残念なことに、アセンブリメタデータに表示されるインターフェイスリストには、クラスが元のC#コードで明示的に実装するインターフェイスを介して継承されたインターフェイスを含む、インターフェイスの「展開」リストが含まれます。これは、FxCopのは、あなたの機能クラスのために、以下のようになります宣言見ていることを意味します

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

このメタデータ表現を考えると、ImplementIDisposableCorrectlyルールはもう少しインテリジェントそれはクラスが実際にあるかどうかを判断しようとする方法についてはする必要がありますIDisposableを再実装します(たとえば、基底クラスがオーバーライド可能なDispose(bool)を持つ場合は、明示的な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 
{ 
    ... 
} 

また、あなたは真剣にgetting rid of the finalizer ...

+0

+1のSupressMessageチップ –

+0

「ファイナライザを取り除く」ためのリンクがリンクの腐敗に敗北しました。もともとhttp://joeduffyblog.com/2005/12/27/never-write-a-finalizer-again-well-almost-never/またはhttp://joeduffyblog.com/2008を指していたかどうかはわかりません/ 02/17/idisposable-finalization-and-concurrency /、あるいは私がまだ見つけていない他の記事があります。リンクを修正するためにあなたの答えを編集できますか? –

+0

完了。 (あなたの最初の推測は正しいです。) –

1

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

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

[SuppressMessage]属性でこれを行うことができます。

4

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

しかし、あなたはIFunctionality : IDisposableのデザインを再考すべきだと思います。ディスポーザブルは本当にIFunctionalityの懸念ですか?私は決定が実装クラスに属すると思う。

+0

'IDisposable'は' IFunctionality'の契約の重要な部分です。残りのシステムで使用されます。しかし、 'Reusable'は' Dispose'の実装を提供しています。従って設計。 –

+0

「IDisposableはIF機能の契約の重要な部分です」 - 実装をインターフェイスに混ぜているように聞こえます。しかし、そのサンプルはあまりにも抽象的すぎて伝えることはできません。 –

+0

「IFunctionality」のコンシューマは、シャットダウン中に指定されたインスタンスを破棄することが重要です。ですから、基本的に 'IFunctionality'はインスタンスをシャットダウンするメソッドを持っており、そのために' IDisposable.Dispose'を使うことにしました。これを設計するための代替方法に関するフィードバックは非常に高く評価されていますが、別の質問に進むはずです。 –

関連する問題