以下を仮定します。
- クラスはメンバーのみを管理しています。
- 一部のメンバーは実装し
IDisposable
ます。 - クラスは
sealed
- クラスはアンマネージ リソースから派生したり、追加したりすることはできません。 - オブジェクトは
using
ステートメント内で使用されます。つまりDispose()
、完了時に呼び出されます。
IDisposable
このクラス には 3 つの可能な実装があります。
- メンバーを
Dispose
呼び出す最小限のメソッド - NO finalizer。Dispose()
IDisposable
IDisposable
Finalizer を使用した標準的な実装ですが、通常の呼び出しがありません。GC.SuppressFinalize(this)
Dispose()
IDisposable
Finalizer (およびGC.SuppressFinalize(this)
call in ) を使用した完全な標準実装Dispose()
。
次の記述は正しいですか? 私はこれを正しく理解しましたか?
- ケース A. のオーバーヘッドは B. および C. よりもわずかに少なくなります。これは、オブジェクトにファイナライザーがないため、GC のファイナライズ キューに入らないためです。GC はコレクションの早い段階でこのオブジェクトを消去できるため、オーバーヘッドはありません。
- ケース B. オブジェクトにファイナライザーがあるため、最終的に GC のファイナライザー キューに入り、ファイナライザーが呼び出されます (抑制されていないため) - ファイナライザーは既に呼び出されているため何もしない dispose を呼び出します。これにより、オブジェクトがファイナライザー キューにあるというわずかなオーバーヘッドと、ファイナライザー呼び出しのごくわずかなオーバーヘッドが発生します。
- ケース C. オブジェクトにファイナライザーがあるため、GC のファイナライザー キューに入れられます。dispose
SuppressFinalize
が呼び出されたため、ファイナライザーは実行されません。この場合でも、オブジェクトがファイナライザー キューに入るというわずかなオーバーヘッドが発生しますが、ファイナライザーは実際には実行されません。
ここでの重要な点は、「呼び出すことでファイナライザーのオーバーヘッドを回避した」と考えたくなるということですが、それは正しくないSuppressFinalize
と思います (明確にしたいと思います)。ファイナライザー キューにあるオブジェクトのオーバーヘッドは依然として発生します。回避しているのは、実際のファイナライザー呼び出しだけです。一般的なケースでは、「私は既に何もしていません」というだけです。
注: ここでいう「完全な標準IDisposable
実装」とは、アンマネージド リソースとマネージド リソースの両方のケースをカバーするように設計された標準実装を意味します (ここでは、マネージド オブジェクト メンバーしかないことに注意してください)。
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
private bool _disposed;
protected virtual void Dispose(bool disposing) {
if (_disposed)
return;
if (disposing) {
// dispose managed members...
}
_disposed = true;
}
~AXCProcessingInputs() {
Dispose(false);
}