为什么"十进制"不是有效的属性参数类型?

Che*_*hen 129 .net c# attributes

这真的令人难以置信,但真实.此代码不起作用:

[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; }  
}
Run Code Online (Sandbox Code Playgroud)

虽然这有效:

[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; }  
}
Run Code Online (Sandbox Code Playgroud)

谁可以告诉我为什么double是可以的,而decimal不是.

djd*_*d87 129

这是CLR限制.只有原始常量或基元数组可用作属性参数.原因是属性必须完全在元数据中编码.这与用IL编码的方法体不同.使用MetaData只会严格限制可以使用的值的范围.在当前版本的CLR中,元数据值仅限于基元,null,类型和基元数组(可能错过了次要基元).

取自JaredPar的这个答案.

基本类型的小数不是基本类型,因此不能在元数据中表示,以防止它成为属性参数.

  • 为什么在CLR中小数不被视为原始类型? (29认同)
  • @koumides我相信答案是类型太大而无法在单个CPU寄存器中表达,因为它是128位 (9认同)
  • 好的,为什么字符串被允许作为属性属性?我想它属于'基元数组'类别,但它是堆分配的(引用类型)... (2认同)
  • @Soren 这不是真的,支持`Enum`。我目前有 2 个自定义属性,一个带有 2 个枚举,另一个带有枚举数组。 (2认同)

Kob*_*obi 53

规格:

属性类的位置和命名参数的类型仅限于属性参数类型,它们是:

  • 其中以下类型:bool,byte,char,double,float,int,long,sbyte,short,string,uint,ulong,ushort.
  • 类型object.
  • 类型System.Type.
  • 枚举类型,前提是它具有公共可访问性,并且嵌套类型(如果有)也具有公共可访问性(属性规范).
  • 上述类型的一维阵列.

  • 正确,但请注意,您引用了旧版本的规范.在C#版本3.0,4.0和5.0中,声明它也可以有类型`sbyte`,`ushort`,`uint`,`ulong`.这似乎可行.但仍然不允许"十进制":-( (9认同)
  • Nullable原语也不受支持. (5认同)