俺的アウトラインプロセッサーをつくる(その1)

では複数のTreeViewの内容を同期しています。そして対応するノードをみつけるためにはTreeNode.Nameプロパティを利用しています。TreeNodeをそのまま使うと同期を保てなくなる場合があるのでTreeNodeExという型を新たに定義してこれを使用しています。

TreeNodeExはこのような構造になっています。

Keyプロパティが同じなら同じノードということになるのですが、同じTreeNodeでも実行するたびに異なるオブジェクトが返されてしまいます。

そこで便利な方法が演算子のオーバーライド。ところがあることを見落としてしまい見事にハマってしまいました。

まず、これはダメ。例外が発生し「aの値がnull」といって怒られます。それから==をオーバーライドするときは!=、Equals、GetHashCodeもオーバーライドしないといけません。

ではこれならどうでしょうか?

aとbがnullの場合もあるので、その場合の処理も書いています。ところが実行するとまたまた問題が・・・。今度はスタックオーバーフローだという。どうなっているのだ?

原因はここに書いています。

Equals() と演算子 == のオーバーロードに関するガイドライン (C# プログラミング ガイド)

演算子 == のオーバーロードでは、(a == b)、(a == null)、または (b == null) を使用して参照が等価であることを確認するというエラーがよくあります。このような場合は、オーバーロードされた演算子 == が呼び出され、無限ループが生じます。無限ループを避けるには、ReferenceEquals を使用するか、型を Object にキャストしてください。

この書き方では演算子==をどうするかを書いているのに、そのなかで==を使ってしまうと無限ループのような状態になってしまうのです。ここはObject にキャストすることにしましょう。

これなら例外は発生しません。