web-dev-qa-db-ja.com

「10進数」が有効な属性パラメータータイプではないのはなぜですか?

それは本当に信じられないですが、本物です。このコードは機能しません:

[AttributeUsage(AttributeTargets.Property|AttributeTargets.Field)]
public class Range : Attribute
{
    public decimal Max { get; set; }
    public decimal Min { get; set; }
}

public class Item
{
    [Range(Min=0m,Max=1000m)]  //compile error:'Min' is not a valid named attribute argument because it is not a valid attribute parameter type 
    public decimal Total { get; set; }  
}

これは機能しますが:

[AttributeUsage(AttributeTargets.Property|AttributeTargets.Field)]
public class Range : Attribute
{
    public double Max { get; set; }
    public double Min { get; set; }
}

public class Item
{
    [Range(Min=0d,Max=1000d)]
    public decimal Total { get; set; }  
}

なぜ10進数ではないのに2倍でよいのか、誰が教えてくれますか。

125
Cheng Chen

これはCLRの制限です。属性パラメーターとして使用できるのは、プリミティブ定数またはプリミティブの配列のみです。理由は、属性を完全にメタデータでエンコードする必要があるためです。これは、ILでコーディングされているメソッド本体とは異なります。 MetaDataを使用すると、使用できる値の範囲が大幅に制限されます。 CLRの現在のバージョンでは、メタデータの値はプリミティブ、null、プリミティブの型および配列に制限されています(マイナーなものが欠落している場合があります)。

this からの回答 JaredPar による回答。

基本型はプリミティブ型ではないため、メタデータで表現できないため、属性パラメーターになることはできません。

125
djdd87

specs から:

属性クラスの位置パラメータと名前付きパラメータのタイプは、次の属性パラメータタイプに制限されています。

  • 次のタイプのいずれか:boolbytechardoublefloatintlongsbyteshortstringuintulongushort
  • タイプobject
  • タイプ System.Type
  • 列挙型。パブリックアクセシビリティがあり、ネストされている型(存在する場合)にもパブリックアクセシビリティ(属性仕様)があります。
  • 上記のタイプの1次元配列。
50
Kobi

この問題の答えは、アトミック型ではないにもかかわらず属性として許可される文字列を使用することです。丸めにより結果の精度が低下するため、倍精度を使用しないでください。

public String MinimumValue
{
    get
    {
        return minimumValueDecimal.ToString();
    }

    set
    {
        minimumValueDecimal = Decimal.Parse(value);
    }
}

private decimal minimumValueDecimal;
1