|
2019/02/04(Mon) 20:03:33 編集(投稿者)
■No90072 (ルパン さん) に返信 > Dispose すると > 配置されているコントロールのデータは破棄されているが
コントロールのデータというよりは、コントロールそのものの破棄です。
繰り返しになりますが、Control クラスにおいては、 Dispose された際に、Controls プロパティに登録されている 子コントロール群も Dispose されるように設計されています。 (子がさらに子を持っていた場合も同様に連鎖します)
このため UserControl の Disposed 時には、子 Label が既に処分されており、 Label の Text プロパティが "" を返してしまうわけです。
いずれにせよ、UserControl や Form や Panel 等の Disposed イベントが 呼ばれたときには、それらの Controls に追加されていた子孫コントロールは 「既に処分されていて利用不可能な状態」であるものとして扱うべきです。
たとえば No90071 でお見せした LabelText プロパティを例に挙げると、 string LabelText { get { return this._labelText; } } という実装の場合には、Dispose された後でも利用できますが、もしもこれを string LabelText { get { return this.lbl.Text; } } にしていた場合は、Dispose 後にはアクセスすべきでは無いということです。
lbl 変数(Label クラス)は IDisposable なオブジェクトですが、 _labelText 変数(String クラス) は IDisposable なオブジェクトでは無いわけで。
> プライベートで指定している各データは消えないんということですか?
Dispose された場合、そのクラスが管理していた情報のうち、 アンマネージなオブジェクトは既に破棄されている状態になります。 一方、マネージリソースの破棄についてはオプション扱いなのでケースバイケースです。
また、幾つかのメンバーについては、破棄後にアクセスした場合に ObjectDisposedException の例外になるように設計されています。 (たとえば Handle プロパティなど)
参考までに Text プロパティの場合、CacheText フラグの付与有無でも動作が異なります。 Label や TextBox 等の場合、Dispose 直後は "" が返却されるようになりますが、 Button、TabPage、ToolStripPanel 等では、Dispose 直前の値が利用されます。
CacheText の有無でどのように変化するか、実験コードを載せておきます。 下記を実行すると、 FormClosing:あいうえお/かきくけこ Disposed:/かきくけこ という結果になることを確認できます。
public partial class Form1 : Form { private Class1 label1; private Class2 label2; public Form1() { InitializeComponent(); Controls.Add(label1 = new Class1() { Text = "あいうえお", Top = 30 }); Controls.Add(label2 = new Class2() { Text = "かきくけこ", Top = 90 });
this.FormClosing += delegate { System.Diagnostics.Debug.WriteLine("FormClosing:" + label1.Text + "/" + label2.Text); }; this.Disposed += delegate { System.Diagnostics.Debug.WriteLine("Disposed:" + label1.Text + "/" + label2.Text); }; } private class Class1 : Label { public Class1() { SetStyle(ControlStyles.CacheText, false); } } private class Class2 : Label { public Class2() { SetStyle(ControlStyles.CacheText, true); } } }
> つまり、Dispose イベント内では
「Dispose イベント」ではなく、過去形表記の 「Disposed イベント」ですね。
> プライベートで指定している各データは消えないんということですか?
private か public かは関係ないですよ。 消えるかどうかは開発者の実装次第です。IDisposable でないオブジェクトは特に。
.NET Framework 自身が提供しているクラス(Label や UserControl) 自体が持つメンバーではなく、 それらを継承したクラス(あるいは自作の class 等)に対して追加したメンバーについては、 Dispose 時にそのデータを処分するかどうかも、開発者自身が決める必要があります。
もし Dispose された時に自作したメンバーの情報も処分する必要があるのなら、 そのコントロールの protected な『void Dispose(bool)』メソッドを オーバーライドする必要があります。(あるいは Disposed イベントを利用する)
|