C# 仕様、10.13 デストラクタに基づく
「インスタンスが破棄されると、そのインスタンスの継承チェーン内のデストラクタが、最も派生したものから最も派生していないものへと順番に呼び出されます。」
私の質問は次のとおりです。
デストラクタが最も派生したものから最も派生していないものへと順番に呼び出されるのはなぜですか? 最小派生から最大派生、または他の順序で順番に呼び出されないのはなぜですか?
C# 仕様、10.13 デストラクタに基づく
「インスタンスが破棄されると、そのインスタンスの継承チェーン内のデストラクタが、最も派生したものから最も派生していないものへと順番に呼び出されます。」
私の質問は次のとおりです。
デストラクタが最も派生したものから最も派生していないものへと順番に呼び出されるのはなぜですか? 最小派生から最大派生、または他の順序で順番に呼び出されないのはなぜですか?
おそらく、派生クラスが基本クラスのメンバーの知識を持っており、デストラクタでそれらを使用する必要がある可能性があるためです。ベース コンストラクターが最初に呼び出された場合、メンバーが使用できないか、オブジェクトの状態がベース デストラクターによって無効な状態になっている可能性があります。
もちろん、基本クラスにはその派生クラスのメンバーに関する知識もアクセス能力もないため、より派生したデストラクタを最初に呼び出すことで問題を回避できます。
オブジェクトは、最も派生していないものから最も派生しているものへと構築されるため、最も派生しているものから最も派生していないものへと分解する必要があります。
派生クラスは基本クラスを認識していますが、基本クラスは派生クラスを認識していません。派生クラスが最も少ないクラスから派生クラスが最も多いクラスにオブジェクトを破棄すると、基本クラスは、派生クラスがプロセスで必要とする可能性があるものを削除します。
たとえば、基本クラスにオブジェクトのリストがあるとします。
public class MyBase {
public List<SomeObject> list;
public MyBase(){
list = new List<SomeObject>();
list.Add(new SomeObject());
list.Add(new SomeObject());
list.Add(new SomeObject());
}
~MyBase() {
foreach (SomeObject obj in list) {
obj.Cleanup();
}
list.Clear();
}
}
派生クラスは、リスト内の各項目に何かを追加します。
public class MyDerived : MyBase {
public MyDerived() {
foreach (SomeObject obj in list) {
obj.SomeProperty = new Handler();
}
}
~MyDerived(){
foreach (SomeObject obj in list) {
obj.SomeProperty.Cleanup();
}
}
}
オブジェクトが破棄されると、追加したものをクリーンアップするために、派生クラスはリストにアクセスする必要があります。基本クラスが最初に破棄された場合、派生クラスはリスト内のオブジェクトにアクセスできません。
(ただし、IDisposable
通常は、オブジェクトの制御されたクリーンアップを処理するためのより良いオプションです。)