2012-01-20 15 views
10

私はインターフェイスの実装を持っており、そのインターフェイスはIDisposableに拡張されています。インターフェイスの私の特定の実装では、私は何も配置する必要はありませんので、空のDispose()メソッドがあります。実装が空のメソッドの場合、Dispose()(FxCopに準拠)を「適切に」実装するにはどうすればよいですか? (CA1063)

FxCopの中に今
public interface IMyStuff : IDisposable 
{ 
} 

public MyStuffImpl : IMyStuff 
{ 
    public void Dispose() 
    { 
    } 
} 

、これはCA1063その結果:だから

Error, Certainty 95, for ImplementIDisposableCorrectly 
{ 
    Resolution : "Provide an overridable implementation of Dispose(
        bool) on 'MyStuffImpl' or mark the type as sealed. 
        A call to Dispose(false) should only clean up native 
        resources. A call to Dispose(true) should clean up 
        both managed and native resources." 
} 
CriticalWarning, Certainty 75, for CallGCSuppressFinalizeCorrectly 
{ 
    Resolution : "Change 'MyStuffImpl.Dispose()' to call 'GC.SuppressFinalize(
        object)'. This will prevent derived types that introduce 
        a finalizer from needing to re-implement 'IDisposable' 
        to call it." 
} 
Error, Certainty 95, for ImplementIDisposableCorrectly 
{ 
    Resolution : "Modify 'MyStuffImpl.Dispose()' so that it 
        calls Dispose(true), then calls GC.SuppressFinalize 
        on the current object instance ('this' or 'Me' in Visual 
        Basic), and then returns." 
} 

、私は2のいずれかの方法でこれを解決することができますように見えます:


クラスsealedを作ります:

public sealed MyStuffImpl : IMyStuff 
{ 
    public void Dispose() 
    { 
    } 
} 

典型的なパターンの一部実装します。私の場合は

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

    private void Dispose(bool disposing) 
    { 
    } 
} 

を、私が今までに延長され、この実装を計画していないので、私はおそらくそれsealedすることによってそれを解決しますが、私は認めます私はそれが封印されているかどうか、それがなぜ重要か理解できません。

また、私のクラスが封印されているので、FxCopはもはやDispose()GC.SupressFinalize(this);を呼び出すはずですが、それは本当に本当ですか?それは、.NETでは、DisplacementのSupressFinalizeを常に呼び出すだけでよいのですか?

+0

おそらく、あなたのインタフェースは、処分する必要のないものを実装するものがあれば、IDisposableを実装すべきではありません。必要に応じて、インタフェースにIDisposable *を実装することもできます。 –

+0

@DBM OPはIDisposableを継承する別のインターフェイスを実装しています。 'IEnumerator 'は一例です。 – phoog

+1

@ DBM:ほとんどの実装が使い捨てである場合、このインタフェースは、インタフェースのユーザが正しく処分するようにする必要があります。 – SLaks

答えて

10

インスタンスにファイナライザがない場合は意味がありません。
クラスにファイナライザがありませんが、sealedでない場合は、継承されたクラスでファイナライザを追加する場合は、SuppressFinalizeのままにしてください。

Dispose(bool)protected virtualであることを除いて、どちらのオプションも正しいです。サブクラスに彼らが管理するすべてのリソースの処分を処理する機会を提供します

protected virtual void Dispose(bool disposing) 
{ 
} 

:あなたの「典型的なパターンの一部を実装する」オプションで

+1

実際には、 'Dispose(bool)'オーバーロードがオーバーライドできないため、2番目のオプションは正しくありません。 +1は、ファイナライザがないオブジェクトでは、 'SuppressFinalize'が無意味であることを指摘しています。 – phoog

+0

クリーンナップファイナライザをクラス用に設計されていない基底クラスに追加しなければならないケースはありますか?そのようなクラスが独自のDisposeメソッドでGC.SuppressFinalizeを処理できない理由はありますか?私はクラスが単に処分の失敗をログに記録するだけの目的で、基底クラスがそれのために設計されていないときにファイナライザでクリーンアップを試みることを目的とするファイナライザを持つことは危険で間違っているように見えます。ファイナライズ可能なクラスのインスタンスをカプセル化する方がはるかに安全です。 – supercat

+0

@supercat:派生クラスが管理されていないリソースを追加する場合。派生クラスは 'Dispose()'をオーバーライドできません。 (なぜ私は 'Dispose(true)'で 'SupressFinalize()'を呼び出せないのか分かりません) – SLaks

1

は、あなたのDispose(bool)方法protected virtualを行う必要があります。これは、「オーバーライド可能なDispose(ブール)の実装を提供する」の「上書き可能」の意味です

もちろん、public virtualもFxCopを満たします。

+0

良い点。多分FxCopはそれについて私に警告しなければなりません;) – CodingWithSpike

+0

@ rally25rsしかし、FxCopは、「Dispose(bool)のオーバーライド可能な実装を提供する」と言ったときにそれについて警告しました。あなたがDispose(bool)のオーバーライドできない実装を提供したときに警告が消えましたか?もしそうなら、それはちょっと変です。 – phoog

+0

私の2番目の例では、Dispose()はプライベートなので、FxCop警告はありません。 – CodingWithSpike

関連する問題