イベントを宣言する 2 つの方法を考えてみましょう。
明示的なadd
/remove
メソッドを使用してイベントを宣言するか、そのようなメソッドを使用せずにイベントを宣言します。
つまり、次のようにイベントを宣言します。
public event EventHandlerType EventName
{
add
{
// some code here
}
remove
{
// some code here
}
}
または、次のように宣言します。
public event EventHandlerType EventName;
問題は、いくつかの点では同じものであり、別の点では完全に異なるということです。
外部コード、つまり、イベントを発行するクラスの外部のコードの観点からは、それらはまったく同じものです。イベントをサブスクライブするには、メソッドを呼び出します。購読を解除するには、別のメソッドを呼び出します。
違いは、上記の 2 番目のコード例では、これらのメソッドがコンパイラによって提供されることですが、それは依然としてそうなる方法です。イベントをサブスクライブするには、メソッドを呼び出します。
ただし、C# でこれを行うための構文は同じで、次のいずれかを行います。
objectInstance.EventName += ...;
また:
objectInstance.EventName -= ...;
したがって、「外部の視点」から見ると、2 つの方法にまったく違いはありません。
ただし、クラス内では違いがあります。
クラス内のEventName
識別子にアクセスしようとすると、実際にfield
はプロパティをサポートするを参照していますが、これは/メソッドを明示的に宣言しない構文を使用している場合に限られますadd
remove
。
典型的なパターンは次のようなものです。
public event EventHandlerType EventName;
protected void OnEventName()
{
var evt = EventName;
if (evt != null)
evt(this, EventArgs.Empty);
}
この場合、 を参照しているとき、EventName
実際には 型のデリゲートEventHandlerType
を保持するフィールドを参照しています。
add
ただし、 /remove
メソッドを明示的に宣言した場合EventName
、クラス内で識別子を参照することは、クラス外と同じようになります。コンパイラは、サブスクリプションを格納するフィールドまたはその他のメカニズムを知っていることを保証できないためです。 .