.NETのAttributeの話(2)
前回の話のつづきです。
続編を書くかどうかちょっと迷いがあったものの、アクセス解析によるとAttributeやAnnotationの検索からたどり着いた人もちらほらといたのでちょっとやる気がでてきました。
.NETの Attribute なり Javaの Annotation は、型情報に自前で何かの拡張を施したいときに使うものです。といっても、自分で定義した拡張なので、.NET CLRなりJava VMはそのことはもちろん関知しません。その拡張情報を見るのもやはりユーザプログラムの仕事です。
なので、一見すると何も楽になっていないように見えるわけですが、「型情報とセットで記述できる」という特徴が見通しの良さを生み、宣言的なプログラミングになっているわけです。
自分のプロジェクトの Poderosa、OmegaChart の両方で使っているテクニックを紹介しておきます。
Enum値の各要素に、説明用の文字列を付加したいことはよくあります。Poderosaからの抜粋を挙げると、
[EnumDesc(typeof(RightButtonAction))]
public enum RightButtonAction {
[EnumValue(Description="Enum.RightButtonAction.ContextMenu")] ContextMenu,
[EnumValue(Description="Enum.RightButtonAction.Paste")] Paste
}
というところがあります。これはマウスの右ボタンクリックでコンテキストメニューを出すかペーストをするかの設定を識別するためのEnum値です。"Enum.RightButtonAction.ContextMenu"というのは文字列の識別子で、日本語版・英語版それぞれで異なる文字列に変換されます。
この項目は例えばダイアログボックス内の選択肢をセットアップするときに使われるわけですが、Enum値から説明文に変換する関数を次のように毎回書くのは大変です。Attributeを使ったときにも、動作上はこの関数と全く同じになります。
public static string DescriptionForRightButtonAction(RightButtonAction value) {
switch(value) {
case RightButtonAction.ContextMenu:
return "コンテキストメニュー";
case RightButtonAction.Paste:
return "ペースト";
...
}
}
同様に説明文を使うEnum型はいろいろな種類があるので、それぞれに個別の関数を用意していると管理が面倒です。
特に、値の種類を増やしたときに説明文の追加をし忘れるというのがやってしまいがちなミスです。このようにswitch文を使っていると、新しい値に対応するcase節を付け忘れていても、実際にその値を引数にswitch文を実行するまでそのことに気づかないのが問題です。
なので、型情報、すなわちenum宣言の中で記述を完結させるのが賢い方法というわけです。これなら書き忘れはまず起こらないですし、書き忘れていることを実行時にチェックすることも可能です。
次回は宣言したAttributeをどう読み出すかを説明予定です。
なんかこの調子だと雑誌のちょっとした記事くらいのボリュームになりそうな気配ですが、こういうのがちょっとずつ肥やしになって後世に検索する人を助けると思えばそれなりに価値はあるかなと思います。
最近のコメント