ジャワ
Java には、「 Finalizer Guardian 」と呼ばれるイディオムがあり、サブクラスがスーパークラスのファイナライザーをオーバーライドするのを防ぎますが、それを呼び出すのを忘れます。以下は、Effective Java Item7の例です。
// Finalizer Guardian idiom
public class Foo {
// Sole purpose of this object is to finalize outer Foo object
private final Object finalizerGuardian = new Object() {
@Override protected void finalize() throws Throwable {
... // Finalize outer Foo object
}
};
... // Remainder omitted
}
この手法を使用すると、ファイナライザーを持つサブクラスがスーパークラスのファイナライザーを呼び出さなくても、プライベート オブジェクトはスーパークラスのファイナライズ コードを実行します。
C#
ただし、C# in a Nutshellのセクション「Calling Dispose from a Finalizer」には、次のような例があります。
class Test : IDisposable {
public void Dispose() // NOT virtual {
Dispose (true);
GC.SuppressFinalize (this); // Prevent finalizer from running.
}
protected virtual void Dispose (bool disposing) {
if (disposing) {
// Call Dispose() on other objects owned by this instance.
// You can reference other finalizable objects here.
// ...
}
// Release unmanaged resources owned by (just) this object.
// ...
}
˜Test() {
Dispose (false);
}
}
また、著者は次のようにも述べています。
このフラグは 、ファイナライザーからの「最終手段モード」ではなく
disposing
、メソッドから「適切に」呼び出されていることを意味します。set toでDispose
呼び出された場合、このメソッドは通常、ファイナライザーを使用して他のオブジェクトを参照しないでください (そのようなオブジェクト自体がファイナライズされ、予測できない状態になる可能性があるため)。disposing
false
質問
しかし、Java のファイナライザー ガーディアンのイディオムを確認すると、内側のプライベート ガーディアン オブジェクトは、ファイナライザー自体を持つことができる外側のオブジェクトを実際に参照/ファイナライズします。これは、 C# の作成者が一言で言えば述べたことに違反しています。
「ファイナライザーで他のファイナライズ可能なオブジェクトを参照する」ことがJavaでは可能であるのにC#では不可能な理由に興味があります。回答ありがとうございます。