¿Por qué “decimal” no es un tipo de parámetro de atributo válido?

Es realmente increíble pero real. Este código no funcionará:

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

Mientras esto funciona:

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

¿Quién puede decirme por qué el doble está bien mientras que el decimal no?

Esta es una restricción CLR. Solo las constantes primitivas o matrices de primitivas se pueden usar como parámetros de atributos. La razón es que un atributo debe codificarse completamente en metadatos. Esto es diferente de un cuerpo de método que está codificado en IL. El uso de MetaData solo restringe severamente el scope de los valores que se pueden usar. En la versión actual del CLR, los valores de metadatos están limitados a primitivos, nulos, tipos y matrices de primitivas (puede haber pasado por alto uno menor).

Tomado de esta respuesta por JaredPar .

Los decimales mientras que un tipo básico no son un tipo primitivo y, por lo tanto, no se pueden representar en metadatos, lo que impide que sea un parámetro de atributo.

De las especificaciones :

Los tipos de parámetros posicionales y nominales para una clase de atributo están limitados a los tipos de parámetros de atributo, que son:

  • Uno de los siguientes tipos: bool , byte , char , double , float , int , long , sbyte , short , string , uint , ulong , ushort .
  • El tipo de object
  • El tipo System.Type .
  • Un tipo de enumeración, siempre que tenga acceso público y los tipos en los que está nested (si lo hay) también tienen acceso público (especificación de atributo).
  • Arrays unidimensionales de los tipos anteriores.

La respuesta a este problema es usar cadenas, que están permitidas como atributos a pesar de no ser un tipo atómico. No use dobles ya que el redondeo hará que los resultados sean menos precisos.

 public String MinimumValue { get { return minimumValueDecimal.ToString(); } set { minimumValueDecimal = Decimal.Parse(value); } } private decimal minimumValueDecimal;