为什么“decimal”不是有效的属性参数类型?

时间:2022-05-07 16:26:01

It is really unbelievable but real. This code will not work:

这真是难以置信,但却是真实的。此代码不起作用:

[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; }  
}

While this works:

虽然这工作原理:

[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; }  
}

Who can tell me why double is OK while decimal is not.

谁能告诉我为什么二重可以,小数不行。

3 个解决方案

#1


104  

This is a CLR restriction. Only primitive constants or arrays of primitives can be used as attribute parameters. The reason why is that an attribute must be encoded entirely in metadata. This is different than a method body which is coded in IL. Using MetaData only severely restricts the scope of values that can be used. In the current version of the CLR, metadata values are limited to primitives, null, types and arrays of primitives (may have missed a minor one).

这是一个CLR限制。只有原语常量或原语数组可以用作属性参数。原因是属性必须完全编码在元数据中。这与在IL中编码的方法主体不同,使用元数据只会严重限制可使用的值的范围。在CLR的当前版本中,元数据值仅限于原语、null、类型和原语的数组(可能漏掉了一个小的)。

Taken from this answer by JaredPar.

来自JaredPar的回答。

Decimals while a basic type are not a primitive type and hence cannot be represented in metadata which prevents it from being an attribute parameter.

虽然基本类型不是基元类型,因此无法在元数据中表示,因此无法将其作为属性参数。

#2


43  

From the specs:

从规格:

The types of positional and named parameters for an attribute class are limited to the attribute parameter types, which are:

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

  • One of the following types: bool, byte, char, double, float, int, long, sbyte, short, string, uint, ulong, ushort.
  • 以下类型之一:bool, byte, char, double, float, int, long, sbyte, short, string, uint, ulong, ushort。
  • The type object.
  • 对象类型。
  • The type System.Type.
  • System.Type类型。
  • An enum type, provided it has public accessibility and the types in which it is nested (if any) also have public accessibility (Attribute specification).
  • 枚举类型,只要它具有公共可访问性,并且嵌套的类型(如果有的话)也具有公共可访问性(属性规范)。
  • Single-dimensional arrays of the above types.
  • 上述类型的一维数组。

#3


0  

The answer to this problem is to use strings, which are allowed as attributes despite not being an atomic type. Don't use doubles as rounding will make the results less accurate.

这个问题的答案是使用字符串,尽管字符串不是原子类型,但可以作为属性。不要使用双精度,因为四舍五入会使结果更不准确。

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

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

private decimal minimumValueDecimal;

#1


104  

This is a CLR restriction. Only primitive constants or arrays of primitives can be used as attribute parameters. The reason why is that an attribute must be encoded entirely in metadata. This is different than a method body which is coded in IL. Using MetaData only severely restricts the scope of values that can be used. In the current version of the CLR, metadata values are limited to primitives, null, types and arrays of primitives (may have missed a minor one).

这是一个CLR限制。只有原语常量或原语数组可以用作属性参数。原因是属性必须完全编码在元数据中。这与在IL中编码的方法主体不同,使用元数据只会严重限制可使用的值的范围。在CLR的当前版本中,元数据值仅限于原语、null、类型和原语的数组(可能漏掉了一个小的)。

Taken from this answer by JaredPar.

来自JaredPar的回答。

Decimals while a basic type are not a primitive type and hence cannot be represented in metadata which prevents it from being an attribute parameter.

虽然基本类型不是基元类型,因此无法在元数据中表示,因此无法将其作为属性参数。

#2


43  

From the specs:

从规格:

The types of positional and named parameters for an attribute class are limited to the attribute parameter types, which are:

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

  • One of the following types: bool, byte, char, double, float, int, long, sbyte, short, string, uint, ulong, ushort.
  • 以下类型之一:bool, byte, char, double, float, int, long, sbyte, short, string, uint, ulong, ushort。
  • The type object.
  • 对象类型。
  • The type System.Type.
  • System.Type类型。
  • An enum type, provided it has public accessibility and the types in which it is nested (if any) also have public accessibility (Attribute specification).
  • 枚举类型,只要它具有公共可访问性,并且嵌套的类型(如果有的话)也具有公共可访问性(属性规范)。
  • Single-dimensional arrays of the above types.
  • 上述类型的一维数组。

#3


0  

The answer to this problem is to use strings, which are allowed as attributes despite not being an atomic type. Don't use doubles as rounding will make the results less accurate.

这个问题的答案是使用字符串,尽管字符串不是原子类型,但可以作为属性。不要使用双精度,因为四舍五入会使结果更不准确。

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

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

private decimal minimumValueDecimal;