- - PR -
デリゲートとイベントについて
投稿者 | 投稿内容 | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2003-02-04 23:09
失礼しました。
先走るあまり"おおぽか"をしてしまいました。 申し訳ありません。 | ||||||||||||||||||||
|
投稿日時: 2003-02-05 10:01
>虎吉さん
>ここが盲点だった気がします。 >デリゲートはクラスであるというのは良く見ましたが・・・ デリゲートはクラスではなく、型(Type)ですね。 それに、盲点だったんですか?私は、虎吉さんは「デリゲート型のフィールドとデリゲート型のイベントが同じように動いて、使い分け方が分からない」と言っていると思っていたんですが。 dlgTestHandlerとeの違いではなく、dとeの違いの話をしているんですよね? >NothingBut.NETFXさん >dはFieldDefとして、eはEventDefとして、それぞれメタデータに書き込まれています。 >dはVB.NETから見てイベントに見えないため、イベント用に用意された便利な機能が使えず、両者の機能は明らかに異なるように見えるのです。 なるほど、つまり.NETでは、イベントというメンバを持つことを可能にすることによって、何か起きたときに他に伝えるという概念を、表現しやすくしたということですかね。 (実際イベントって良く使うし) | ||||||||||||||||||||
|
投稿日時: 2003-02-06 10:44
始めはさらっとこの部分を読み流していましたが、実際にデリゲート型のフィールドとデリゲート型のイベントを作って色々操作してると、決定的な違いを見つけました。 それは、「イベントは、それをメンバとするクラス以外からは起動できない」ということです。 (そんなもん前から知ってるよ、とか言われそうですが) 外から関数(メソッド)を登録するためにはもちろんpublicでなければいけませんが、publicだからといって外から好き勝手にイベントを起動されるようなことがあってはなりません。ここから見ても、イベントは「オブジェクト内で変化等があったときに呼び出して欲しいメソッドを登録しておけ」という意味合いのものなんでしょうね。 デリゲート型のフィールドは外からでも起動(そのフィールドが指しているメソッドを呼び出すこと)ができました。 | ||||||||||||||||||||
|
投稿日時: 2003-02-06 12:27
>デリゲート型のフィールドは
>外からでも >起動(そのフィールドが指しているメソッドを呼び出すこと)ができました。 私も今 コードを打って確認しました。 デリゲードの場合 デリゲードフィールドを使ってデリゲードを登録したクラスの そのフィールドを使えば デリゲードを登録していない他のクラスからでも起動可能ですね。 | ||||||||||||||||||||
|
投稿日時: 2003-02-06 19:27
デリゲートはILレベルではクラスです。コンパイラが展開してくれます。虎吉さんがおっしゃっているのはそのことだと思います。ですから、「型」というのも正しいですし、「クラス」というのも正しいでしょう。
それでは次のようなC#のコードはどう説明すればいいでしょうか。
eはイベントです。eに登録したものが外部から呼び出されて、結果としてeイベントが発生したことになっています。 わざと変なコードを書いているかのように思われるかもしれませんが、結局のところC#コンパイラが行うのは「internal EventHandler f;」というコードを、次のように展開することです。これは、add/removeアクセッサを書かないものぐさな私たちのためにデフォルト実装を提供するという親切心でしかありません。
お分かりのように、デフォルトの展開方式では「+=(AddHandler)」で設定されたイベントハンドラを格納するフィールドがprivateに宣言されるため、外部からこのデリゲート型のフィールドにアクセスできなくなり、外部から起動できないように見えるだけです。 上記のように自分でadd/removeアクセッサを定義する場合は、格納するフィールドも自分で定義しなければなりません。自分で定義するので、privateにしなければならないわけでもありません。ニーズに応じたアクセス修飾子を付けることができます。 イベントというのは、クラスの内部ではフィールドと2つのアクセッサメソッドの対でしかありません。ちょうどプロパティが2つのアクセッサメソッドの対でしかないのと同じです。 そういうわけですから、私はイベントそのものに
というようなセマンティクスはないと思っています。もっとも、ある種の設計パターン(ベストプラクティス?)として、イベントをそのように扱うべきだ、という議論であればそういうパターンを定義すること自体に反対ではありません。 | ||||||||||||||||||||
|
投稿日時: 2003-02-07 09:45
アセンブリを見てみましたが、確かに「System.MulticastDelegateを拡張したクラスだ」みたいに書いてありました。 でもそうすると、構造体も列挙型も全部クラスということで、プログラマのコミュニケーションには不都合ですね。 「クラスのさぁ・・・」 「クラス?どんな。」 「System.ValueTypeもSystem.EnumもSystem.MulticastDelegateも親クラスとして持っていないクラスのさぁ・・・」 みたいな。
アクセッサを定義しないイベントを定義すると、privateなデリゲート型フィールドとaddアクセッサ、removeアクセッサが作られるんですね。 確かに私はものぐさですが、良く使われる形の実装をデフォルトで提供するというこなんでしょう。 一段と.NETの理解が深まりました。これは勉強になりました。 ありがとうございました。 | ||||||||||||||||||||
|
投稿日時: 2003-12-01 14:33
イベントとデリゲートの違いについて
調べていてこのスレッドにたどり着きました。 このスレッドでいわれている”イベント”は "event"キーワード付きで宣言されたもののことだと思うのですが、そうすると、 以下の
は"event"キーワード付きで宣言されたイベントの説明補足 としては少し違うような気がしました。 コンパイラが展開するコードの内容については 非常に参考になりました。 [ メッセージ編集済み 編集者: ナキヲ 編集日時 2003-12-01 14:34 ] | ||||||||||||||||||||
|
投稿日時: 2003-12-01 14:45
おっと、
add/removeの使用はevent独自のものなんですね。。 (今ドキュメント見て知りました) 失礼しました。 いずれにしてもeventキーワードのついたデリゲートは 標準で ・eventが定義されたクラスからしか起動できない ・+/−で、使用側が知っているハンドラの追加、登録しか できない。 ということですね。 |