C#の場合

先日のエントリでは、Javaアノテーションは属性のデフォルト値を省略することで、結果としてビルド時に必須制約を付けられると書いた。
Javaのアノテーションに纏わる小ネタ
C#には同様の機能は無いと思っていたのだが、実際にはなちゃさんにコメントを頂いた通りで、C#の場合アノテーション(カスタム属性)はJavaのようにプロキシではなく具象クラスとして扱われること、実体化にはコンストラクタが必要なことを利用することで、同様にビルド時に制約を付加することができる。

C#のカスタム属性はメタデータとしてコード記述する際に、Javaアノテーションのように属性(プロパティとして実装されている)を記述する他に、インスタンスを生成する際のコンストラクタのパラメタを指定することもできる。

例として前回のJavaアノテーションと同等であるBindAttributeクラスを用意してみよう。

[AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = false)]
public class BindAttribute : Attribute
{
    private Type frameType;
    public BindAttribute(Type frameType)
    {
        this.frameType = frameType;
    }
    public Type FrameType 
    {
        get { return this.frameType; }
        set { this.frameType = value; }
    }
}

このカスタム属性だが、実際に記述する際にコンストラクタのパラメタが必須制約と同じ役目を果たす。

[Bind]
public class Action {
}

このコードはビルドしようとするとエラーになる。

引数を '0' 個指定できる、メソッド 'BindAttribute' のオーバーロードはありません。

コンストラクタパラメタと属性は当然独立しているので、この場合

[Bind(FrameType = typeof(Fookorm)] //これもビルド時にエラー

でもだめで、

[Bind(typeof(FooForm)] 

と記述する必要がある。久しぶりにC#に戻ってみたが、やはり忘れてるなぁ。