- PR -

デリゲートとイベントについて

投稿者投稿内容
へるまろ
ベテラン
会議室デビュー日: 2003/02/04
投稿数: 57
お住まい・勤務地: 東京
投稿日時: 2003-02-04 15:38
以下のようにデリゲートとイベントを定義したとします。
public delegate void dlgTestHandler();

public class TestClass
{
public dlgTestHandler d;
public event dlgTestHandler e;

public Form()
{
d += new dlgTestHandler(this.OnTest);
e += new dlgTestHandler(this.OnTest);
}

private void OnTest()
{
MessageBox.Show("Fire1!");
}
}

というクラスを作った場合、別のクラスで

class TestClass2
{
private TestClass cls = new TestClass();

TestClass2()
{
cls.d;
cls.e;
}
}

これで両方ともメッセージボックスを表示しますが、
このデリゲートとイベントの使い分けがどうも分かりません・・

根本的に勘違いしてるかもしれませんが、
デリゲートとイベントはどのように使い分ければ
良いのでしょうか?

宜しくお願いします。
まゆりん
ぬし
会議室デビュー日: 2002/08/12
投稿数: 539
お住まい・勤務地: よこはま
投稿日時: 2003-02-04 15:42
引用:

虎吉さんの書き込み (2003-02-04 15:38) より:

根本的に勘違いしてるかもしれませんが、
デリゲートとイベントはどのように使い分ければ
良いのでしょうか?

宜しくお願いします。



こことか読まれても分かりませんでしたか?

[ メッセージ編集済み 編集者: まゆりん 編集日時 2003-02-04 15:43 ]
へるまろ
ベテラン
会議室デビュー日: 2003/02/04
投稿数: 57
お住まい・勤務地: 東京
投稿日時: 2003-02-04 16:11
レスありがとうございます。

"delegateは処理を他にゆだねるものだが、
eventはクラス内の出来事を外部に伝えるものである"

ということで使い分けは理解できたのですが、
例えばやろうと思えば
"eventは処理を他にゆだねるものだが、
delegateはクラス内の出来事を外部に伝えるものである"
という逆の使い方も可能と思うのですが,各々の機能的に
向いていなかったり、機能が足りなかったりということ
があるのでしょうか?

私の読解力が足りなかったのだと思いますが、リファレンスなども
参考にしてもうちょっと調べてみます。
一郎
ぬし
会議室デビュー日: 2002/10/11
投稿数: 1081
投稿日時: 2003-02-04 16:24
私も違いがピンと来ない人間です。

delegateは処理を他にゆだねるものだが、eventはクラス内の出来事を外部に伝えるものである。
か。
イベントは、「俺がこう(クリックされた・Textが変わった等)なったときに知らせて欲しいやつは、登録しておけ。」ということで公開するもので、デリゲートは「処理するのはこのメソッド」とメソッドへの引数で渡したりクラスのメンバとして保持していたり。まさに関数のポインタのような使い方、というイメージを私は持っていますが。

これは、プログラマーが理解しやすいように何に使うかで分けているという事なんでしょうかね。
eventキーワードが無くても、動作的には何も困らないと思いますが。
へるまろ
ベテラン
会議室デビュー日: 2003/02/04
投稿数: 57
お住まい・勤務地: 東京
投稿日時: 2003-02-04 16:58
一郎さん、レスありがとうございます。

イベントはマルチキャスト
デリゲートはユニキャスト
という風にでも機能が違ってくれていれば納得
も楽だったのですが・・

あまり考えずにそういうものとして使うのが
良いのでしょうか。
NothingButXMLInfoSet
大ベテラン
会議室デビュー日: 2002/07/16
投稿数: 116
投稿日時: 2003-02-04 19:30
デリゲートとイベントを比べることは、クラスとプロパティを比べることと同じです。そのような比較はナンセンスだという点でも同じです。プロパティに対して「textBox1.Text.ToUpper();」のようにメソッドの呼び出しができるからといって、「プロパティはクラスに似ている」とは言わないでしょう。

引用:
delegateは処理を他にゆだねるものだが、eventはクラス内の出来事を外部に伝えるものである。


イベントだって他に処理をゆだねます。クラス内の出来事に関して、自分の内部で処理を完結できないから他者に処理してもらうのがイベントでしょう。虎吉さんの例ではdもeも自分のメソッドを結果的に呼びますが、dに他のクラスのメソッドを設定していれば、dだってクラス内の出来事を外部に伝えることになります。このような比較は単純に誤りなのです。

本質的に、デリゲートはクラス、構造体、インターフェイス、列挙などと同じ意味での「型」です。イベントは、メソッド、フィールド、プロパティなどと同じ意味での「型のメンバー」です。従って両者はまったく異なります。フィールドやプロパティは、int(Integer)、string(String)などの型が適用されます。同様に、イベントにはEventHandler、DataGridCommandEventHandlerなどの型が適用されます。

.NET Frameworkで型として扱えるものであれば何でもフィールドやプロパティの型として適用できますが、イベントに適用できる型はデリゲート型だけに制限されています。つまり、当初の虎吉さんの例では、dはTestClassのフィールドで型がdlgTestHandlerです。eはTestClassのイベントで、型はたまたまdと同じdlgTestHandlerです。同じクラスの中に、たまたま同じint(Integer)型のフィールドとプロパティが同居することはよくありますよね。それと同じです。

本質論から離れて機能だけに的を絞っても、両者はまったく異なります。虎吉さんの例のTestClassをコンパイルしてILDASM.exeなどのツールで見てみればわかるのですが、dはFieldDefとして、eはEventDefとして、それぞれメタデータに書き込まれています。

普段C#を使っているとわかりづらいのですが、普段VB.NETを使っている開発者には、この違いが非常に重要です。VB.NETにはWithEventsやHandlesなどの「イベントを扱うための特殊機能」が組み込まれています。この機能は、それがメタデータ上でイベントと認識されなければ使えません。つまり、虎吉さんのTestClassをVB.NETから利用しようとすると、dはVB.NETから見てイベントに見えないため、イベント用に用意された便利な機能が使えず、両者の機能は明らかに異なるように見えるのです。結局本質の話に戻ってしまうのですが、dは単なるデリゲート型のフィールドであるのに対して、eは.NET Frameworkご自慢のイベントであるという本質的な違いがあるのです。

最初に戻りますが、イベントがたまたま型としてデリゲート型しか適用できないメンバーであるからといって、イベントは型ではなくあくまでも型のメンバーとなる要素なのです。

-----------

ちなみに、C#を使っていても、dとeとの違いを際立たせることはできます。イベントにはaddアクセッサremoveアクセッサが定義できますが、フィールドには当然できません。addアクセッサとremoveアクセッサは普段あまり使わないかもしれませんが、この本になかなか面白い使い方が出ています。お手元にあったらイベントの項を参照してみてください。
へるまろ
ベテラン
会議室デビュー日: 2003/02/04
投稿数: 57
お住まい・勤務地: 東京
投稿日時: 2003-02-04 20:01
NothingBut.NETFXさん、詳細なレスを書いて頂いて
本当にありがとうございます。

引用:

本質的に、デリゲートはクラス、構造体、インターフェイス、列挙などと同じ意味での「型」です。イベントは、メソッド、フィールド、プロパティなどと同じ意味での「型のメンバー」です。



ここが盲点だった気がします。
デリゲートはクラスであるというのは良く見ましたがイベントについては
あいまいなままにしておりました。
この引用文に気づくとそもそもデリゲートとイベントで比較すること自体が
ナンセンスなんだと思い知らされました。

引用:

VB.NETにはWithEventsやHandlesなどの「イベントを扱うための特殊機能」が組み込まれています。この機能は、それがメタデータ上でイベントと認識されなければ使えません。つまり、虎吉さんのTestClassをVB.NETから利用しようとすると、dはVB.NETから見てイベントに見えないため、イベント用に用意された便利な機能が使えず、両者の機能は明らかに異なるように見えるのです。結局本質の話に戻ってしまうのですが、dは単なるデリゲート型のフィールドであるのに対して、eは.NET Frameworkご自慢のイベントであるという本質的な違いがあるのです。



この引用文は本当に助かりました。
こうして具体的な例を示して頂いたおかげで本当に納得できました。

ずっとC++で開発をしていたのですがイベントやデリゲートは新しい
(同様の機能は実装できますが)
機能だったので面白いと思う一方でつまづいてしまいました。

お恥ずかしながらJeffrry Richterの書籍は手元にありイベントとデリゲート
の章は何度か読んだのですが・・読解力のなさを恨みたくなります。
もう一度NothingBut.NETFXさんの引用を踏まえて一から読み直します。

最後に本当にありがとうございました。
パダワン
会議室デビュー日: 2002/07/27
投稿数: 15
投稿日時: 2003-02-04 22:56
このコードはおかしいです。

登録されたイベントやデリゲードは、それらと同じクラス内からでしか呼び出すことができないので
TestClassで登録されたイベントとデリゲードをTestClass2から呼び出すことはできません。

ビルドできるコードを載せてください。

スキルアップ/キャリアアップ(JOB@IT)