- PR -

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

投稿者投稿内容
toppo
ベテラン
会議室デビュー日: 2003/10/28
投稿数: 89
お住まい・勤務地: 東京・池袋
投稿日時: 2004-02-26 22:32
突然よこやりを入れるようですみませんが、
Toppoです。

引用:

それでは次のようなC#のコードはどう説明すればいいでしょうか。

コード:
using System;
class App {
    static void Main() {
        B b = new B();
    }
}

class A {
    internal EventHandler ee;
    internal event EventHandler e {
        add { ee = value; }
        remove { ee = null; }
    }
}

class B {
    internal B() {
        A a = new A();
        a.e+= new EventHandler(MyE);
        a.ee(this, EventArgs.Empty);
    }
    private void MyE(object s, EventArgs e) {
        Console.WriteLine("イベント発生");
    }
}


eはイベントです。eに登録したものが外部から呼び出されて、結果としてeイベントが発生したことになっています。

わざと変なコードを書いているかのように思われるかもしれませんが、結局のところC#コンパイラが行うのは「internal EventHandler f;」というコードを、次のように展開することです。これは、add/removeアクセッサを書かないものぐさな私たちのためにデフォルト実装を提供するという親切心でしかありません。

コード:
private EventHandler f;
internal void add_f(EventHandler value) { this.f += value; }
internal void remove_f(EventHandler value) { this.f -= value; }


お分かりのように、デフォルトの展開方式では「+=(AddHandler)」で設定されたイベントハンドラを格納するフィールドがprivateに宣言されるため、外部からこのデリゲート型のフィールドにアクセスできなくなり、外部から起動できないように見えるだけです。

上記のように自分でadd/removeアクセッサを定義する場合は、格納するフィールドも自分で定義しなければなりません。自分で定義するので、privateにしなければならないわけでもありません。ニーズに応じたアクセス修飾子を付けることができます。

イベントというのは、クラスの内部ではフィールドと2つのアクセッサメソッドの対でしかありません。ちょうどプロパティが2つのアクセッサメソッドの対でしかないのと同じです。

そういうわけですから、私はイベントそのものに

引用:

ここから見ても、イベントは「オブジェクト内で変化等があったときに呼び出して欲しいメソッドを登録しておけ」という意味合いのものなんでしょうね。


というようなセマンティクスはないと思っています。もっとも、ある種の設計パターン(ベストプラクティス?)として、イベントをそのように扱うべきだ、という議論であればそういうパターンを定義すること自体に反対ではありません。



internal EventHandler ee;

internal event EventHandler ee;
とすれば、外部から呼ばれませんよね。
プロパティとして明示的に外部に公開しているので呼べるという事ですね。
ですから、
引用:

ここから見ても、イベントは「オブジェクト内で変化等があったときに呼び出して欲しいメソッドを登録しておけ」という意味合いのものなんでしょうね。


は私もそう思います。

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