.NETにおいてイベントとは、System.MulticastDelegateのインスタンスである。
MulticastDelegateは参照型なので、ただ宣言しただけで中身を入れていなければnullである。
ここまでは問題ない。
疑問に思うのは、それがnullでなくなる瞬間はいつか、ということだ。
例えば、こうするとnullではなくなる。
button1.Click += new EventHandler( button1_Click );
ここで興味深いのは、Clickイベントはイベントのインスタンスであり、このコードを実行するまではnullであり、+=演算子は通常、既存のインスタンスに対して使うものだ(という先入観がある)ということだ。
同様に、-=演算子を使って、すべてのハンドラを除去すると、イベントインスタンスはnullになる。
+=も-=もC++から受け継いだ演算子である。
C++でこれらの演算子を実装するときには、「自身のインスタンスに対してもう一方の引数を加え/差し引き、自身のインスタンスを返す」というのが定石である。
だから、自身のインスタンスがnullならば使えないという気がする。
だが、定石ではあるが、絶対ではない。自身のインスタンスを返さなくともよいのだ。
そもそも、C#では演算子はすべてstaticであるため、「自身のインスタンス」などというものは無い(その場合は「第一引数に第二引数を足して/引いて、第一引数を返す」というのが直感的ではあるが、やはり絶対ではない)。
MulticastDelegateに対する+=、-=は、それぞれ、静的メソッドであるCombine、Removeに置き換えられる。
左辺が第一引数に、右辺が第二引数に渡され、結果が左辺に格納される。
Combineは第一引数がnullなら第二引数を返し、Removeは第一引数の呼び出しリストから第二引数のハンドラを除いた結果、呼び出しリストが空になればnullを返すという挙動を示す。
このため、これらの演算子の結果は、nullだったものが非nullになったり、nullでないものがnullになったりする。
当初は、nullとの比較はGetInvocationListが空であるかどうかに置き換えられると思っていた。空とnullは違うのだから、それはいかんだろうと思っていたのだが、調べてみたら以上の通りだった。
…空とnullは違うのだから、空になったらnullを返すというのもどうかとは思うのだが。