usar valores decimales como parámetros de atributo en c #?

Respuestas:

121

Esta es una restricción de CLR. Sólo las constantes primitivas o las matrices de primitivas pueden utilizarse como parámetros de atributo. La razón es que un atributo debe estar codificado completamente en metadatos. Esto es diferente al cuerpo de un método que está codificado en IL. El uso de metadatos solo restringe severamente el alcance de los valores que se pueden usar. En la versión actual de CLR, los valores de metadatos se limitan a primitivas, nulos, tipos y matrices de primitivas (es posible que se hayan perdido una menor).

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 evita que sea un parámetro de atributo.

JaredPar
fuente
5
¿Sigue siendo un problema con Framework 4.0? y 4.5, 4.6.x?
midspace
@midspace, no es realmente un problema, solo una limitación, impuesta por el diseño. Es lamentable, pero hay muchas posibilidades de que nunca desaparezca.
Bruno Brant
1
"Solo las constantes primitivas o las matrices de primitivas pueden utilizarse como parámetros de atributo". No parece ser exactamente cierto, por ejemplo, System.Type también está permitido: msdn.microsoft.com/en-us/library/aa664615(v=vs.71).aspx
DixonD
Using MetaData only severely restricts the scope of values that can be used- ¿Por qué es eso? Los metadatos se pueden utilizar para señalar definiciones de tipos. Por ejemplo, cuando define un campo en una clase normal, se emiten metadatos que incluyen el nombre del campo y su tipo (Cualquier tipo, no solo primitivas). No entiendo por qué esto no se puede usar para atributos.
Winger Sendon
15

Tengo el mismo problema. Considero usar cadenas . Esto no es seguro para los tipos, pero es legible y creo que podremos escribir números válidos en cadenas :-).

class BlahAttribute : Attribute
{
  private decimal value;

  BlahAttribute(string number)
  {
    value = decimal.Parse(number, CultureInfo.InvariantCulture);
  }
}

[Blah("10.23")]
class Foo {}

No es una belleza, pero después de considerar todas las opciones, es lo suficientemente bueno.

Stefan Steinegger
fuente
1
Parece que así es como mbUnit hace frente a vkreynin.wordpress.com/2007/05/25/…
Andy Dent
2

Cuando me encontré con esta situación, terminé exponiendo las propiedades del atributo como un Double, pero dentro del atributo las traté como Decimal. Lejos de ser perfecto, pero para los casos simples, podría ser lo que necesita.

ckittel
fuente
1

Para trucos en tiempo real con atributos, estoy usando la clase TypeConverter .

Avram
fuente
0

Puede utilizar el siguiente constructor. Cuando tiene un literal decimal en el código C #, el compilador de C # emite una llamada a este constructor.

Decimal(Int32, Int32, Int32, Boolean, Byte)

Editar: sé que esto no es conveniente.

Sam Harwell
fuente
2
Si esto funcionó en un atributo, supongo que simplemente usar el sufijo "m" también lo haría, pero tampoco lo hace (Usando System.ComponentModel.DefaultValueAttribute como mi prueba)
xr280xr