C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[7]: イベントについて


(過去ログ 57 を表示中)

[トピック内 10 記事 (1 - 10 表示)]  << 0 >>

■32373 / inTopicNo.1)  イベントについて
  
□投稿者/ nyari (1回)-(2009/02/05(Thu) 16:46:19)

分類:[.NET 全般] 

初めて投稿させていただきます。
イベントについて質問があります。

例えば、ボタンを動的にフォームに追加して、イベントを追加した際に下記のようなコードを追記します。

Button btn = new Button();
this.Control.Add(btn);
btn.Click += new System.EventHandler(this.button_Click);

そして、何かのタイミング(他のボタンクリック等…)で追加したボタンの削除を行う際は、

this.Control.Remove(btn); // ←btnは当ステップ以前で対象ボタンを取得しています…
btn.Dispose();

としますが、コントロールを削除するタイミングで追加したイベントを

>btn.Click -= new System.EventHandler(this.button_Click);

として削除する必要はあるのでしょうか?
それとも、紐づいているコントロールが解放されればイベント自体も解放されるのでしょうか???

よろしくお願いします。
引用返信 編集キー/
■32374 / inTopicNo.2)  Re[1]: イベントについて
□投稿者/ 囚人 (317回)-(2009/02/05(Thu) 17:05:43)
ん〜、難しいですね。あんまり細かい事気にしなくていいでしょうけど、追加と削除は逆の事をやった方が良さそうな気はしますよね。
おそらくですが、イベントを外さないとデリゲートのインスタンスが残ったままになる可能性はあるかもしれません。
Control は Remove されたときに GC の対象にならないように、また、子ウィンドウは必ず親ウィンドウが必要だという Windows のルールに則るために、親のいない Control は WindowsFormsParkingWindow という隠しウィンドウの子になってしまいます。ですので、その Button が GC の対象となる条件を満たせば大丈夫かもしれませんが、Add したものを Remove するという事は、GC の対象をなかなか満たせない設計になっているのではないでしょうか。

引用返信 編集キー/
■32376 / inTopicNo.3)  Re[2]: イベントについて
□投稿者/ 囚人 (318回)-(2009/02/05(Thu) 17:09:13)
修正

>GC の対象をなかなか満たせない設計になっているのではないでしょうか。


GC の対象となる条件をなかなか満たせない設計になっているのではないでしょうか。


あと、WindowsFormsParkingWindow と GC に関連はないかも。正確ではないのでご注意を。
引用返信 編集キー/
■32378 / inTopicNo.4)  Re[1]: イベントについて
□投稿者/ 渋木宏明(ひどり) (1062回)-(2009/02/05(Thu) 17:14:44)
渋木宏明(ひどり) さんの Web サイト
> それとも、紐づいているコントロールが解放されればイベント自体も解放されるのでしょうか???

例示されているパターン(イベントハンドラが、そのコントロールを配置しているフォームに所属している)なら、明示的にイベントハンドラの登録を解除しなくても支障はありません。

ですが、例えばイベントハンドラが動的に追加・削除される別のコントロールに所属している場合などは、明示的にイベントハンドラの登録を解除してやらなければならない場合も出てきます。

個人的には、見た目の対称性が高くて気持ちいいので、解除コード書いちゃいますけど。

引用返信 編集キー/
■32379 / inTopicNo.5)  Re[2]: イベントについて
□投稿者/ 渋木宏明(ひどり) (1063回)-(2009/02/05(Thu) 17:17:30)
渋木宏明(ひどり) さんの Web サイト
> Control は Remove されたときに GC の対象にならないように、また、子ウィンドウは必ず親ウィンドウが必要だという Windows のルールに則るために、親のいない Control は WindowsFormsParkingWindow という隠しウィンドウの子になってしまいます。ですので、その Button が GC の対象となる条件を満たせば大丈夫かもしれませんが、Add したものを Remove するという事は、GC の対象をなかなか満たせない設計になっているのではないでしょうか。

でも、Dispose() したら ParkingWindow から外されるんじゃないすか?

でないと、いつまででもクラスインスタンスが残ってしまうと思うけど。
引用返信 編集キー/
■32382 / inTopicNo.6)  Re[3]: イベントについて
□投稿者/ nyari (3回)-(2009/02/05(Thu) 17:32:36)
回答ありがとうございます。

囚人さん
> ん〜、難しいですね。あんまり細かい事気にしなくていいでしょうけど、追加と削除は逆の事をやった方が良さそうな気はしますよね。
> おそらくですが、イベントを外さないとデリゲートのインスタンスが残ったままになる可能性はあるかもしれません。

可能性はあるのですか…
なら、一応はずしておくのが無難なのでしょうか…

> Control は Remove されたときに GC の対象にならないように、また、子ウィンドウは必ず親ウィンドウが必要だという Windows のルールに則> るために、親のいない Control は WindowsFormsParkingWindow という隠しウィンドウの子になってしまいます。ですので、その Button が GC > の対象となる条件を満たせば大丈夫かもしれませんが、Add したものを Remove するという事は、GC の対象をなかなか満たせない設計になって> いるのではないでしょうか。

C#初心者なもので…
もう少し、GCなどメモリの管理等の学習をしておく必要がありますね…
囚人さんが記述されているキーワードを元に少し調べてみようと思います。


渋木宏明(ひどり) さん

> ですが、例えばイベントハンドラが動的に追加・削除される別のコントロールに所属している場合などは、明示的にイベントハンドラの登録を解> 除してやらなければならない場合も出てきます。

現状複数のボタンに対して、同一イベントを追加しようと思っています。
その場合は上記に書いてあるように、明示的にイベントハンドラの登録解除をする必要あるって事ですよね…

> 個人的には、見た目の対称性が高くて気持ちいいので、解除コード書いちゃいますけど。

解除コードを書いておく分にはとくに問題はないということですよね?
現状のところは、イベントの解除を行っておくことにします。




引用返信 編集キー/
■32387 / inTopicNo.7)  Re[4]: イベントについて
□投稿者/ 渋木宏明(ひどり) (1065回)-(2009/02/05(Thu) 19:49:16)
渋木宏明(ひどり) さんの Web サイト
> 現状複数のボタンに対して、同一イベントを追加しようと思っています。
> その場合は上記に書いてあるように、明示的にイベントハンドラの登録解除をする必要あるって事ですよね…

イベントハンドラの登録解除が必要かどうかは、イベントハンドラを公開するオブジェクト(イベントリスナ)の寿命を基準に考えます。

イベントリスナがイベントソースよりも先に寿命を終わるようなら、その時点でイベント接続を解除するべきです。

これを怠ると、イベントソース→イベントリスナの参照が残っているため、不要なはずのイベントリスナのインスタンスがいつまでたっても解放されず、イベントも伝達されてしまいます。

> 解除コードを書いておく分にはとくに問題はないということですよね?

↑で書いたように、解除のタイミングも重要です。
引用返信 編集キー/
■32390 / inTopicNo.8)  Re[5]: イベントについて
□投稿者/ nyari (5回)-(2009/02/05(Thu) 20:51:59)
No32387 (渋木宏明(ひどり) さん) に返信

理解不足でスミマセン…
最初に記載したサンプルでは…
 イベントリスナ⇒this(画面クラス)
 イベントソース⇒btn(ボタンコントロール)
でいいのでしょうか?

その場合…
>
> イベントリスナがイベントソースよりも先に寿命を終わるようなら、その時点でイベント接続を解除するべきです。
>
画面クラスがボタンコントロールより終わることはないので特に接続解除は必要ないということなのでしょうか?

逆に、イベントリスナがイベントソースよりも先に寿命を終わるようなケースというのは、
 (例)上記の場合だと、画面クラスとは別のクラスのインスタンスのメソッドをイベントへ紐付けておき、
    紐付けたメソッドが所属するインスタンスを解放される場合など…
という感じなのでしょうか???
具体的にどのようなケースなのかわかれば少しは理解ができるような気がしまして…

長々とすみませんm(_ _)m
よろしくお願いします。
引用返信 編集キー/
■32392 / inTopicNo.9)  Re[6]: イベントについて
□投稿者/ 渋木宏明(ひどり) (1066回)-(2009/02/05(Thu) 21:59:49)
渋木宏明(ひどり) さんの Web サイト
2009/02/05(Thu) 22:02:05 編集(投稿者)

> 画面クラスがボタンコントロールより終わることはないので特に接続解除は必要ないということなのでしょうか?

そです。

> 逆に、イベントリスナがイベントソースよりも先に寿命を終わるようなケースというのは、
>  (例)上記の場合だと、画面クラスとは別のクラスのインスタンスのメソッドをイベントへ紐付けておき、
>     紐付けたメソッドが所属するインスタンスを解放される場合など…
> という感じなのでしょうか???

例えば、そうです。

> 具体的にどのようなケースなのかわかれば少しは理解ができるような気がしまして…

僕も自力では数回しか実装したことないんで、単純な例が思い浮かびませんが、そういうケースがあることはあります。

引用返信 編集キー/
■32396 / inTopicNo.10)  Re[7]: イベントについて
□投稿者/ nyari (7回)-(2009/02/06(Fri) 09:09:05)
2009/02/06(Fri) 09:09:27 編集(投稿者)

No32392 (渋木宏明(ひどり) さん) に返信

紐付けを解消しなくてはいけない理由を逆に思ってしまっていました…
やっと、イベント削除をする理由等わかりました。
長々とありがとうございました。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -