90

I've been trying to use decimal values as params for a field attribute but I get a compiler error.

I found this blog post link saying it wasn't possible in .NET to use then, does anybody know why they choose this or how can I use decimal params?

RBT
  • 24,161
  • 21
  • 159
  • 240
rjlopes
  • 2,430
  • 4
  • 21
  • 23
  • Possible duplicate of [Why "decimal" is not a valid attribute parameter type?](https://stackoverflow.com/questions/3192833/why-decimal-is-not-a-valid-attribute-parameter-type) – StayOnTarget Jun 28 '19 at 15:16

5 Answers5

133

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).

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.

JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
  • 5
    Is this still an issue with Framework 4.0? and 4.5, 4.6.x? – midspace Mar 31 '16 at 10:00
  • @midspace, not really an issue, just a limitation, imposed by design. It's unfortunate, but good chances that it may never go away. – Bruno Brant Apr 02 '16 at 17:45
  • 2
    "Only primitive constants or arrays of primitives can be used as attribute parameters." It doesn't seem to be precisely true, for instance, System.Type is also allowed: https://msdn.microsoft.com/en-us/library/aa664615(v=vs.71).aspx – DixonD Aug 03 '16 at 12:00
  • `Using MetaData only severely restricts the scope of values that can be used` - Why is that though? Metadata can be used to point to type definitions. For example, when you define a field in a regular class, metadata is emitted which includes the name of the field and it's type (Any type, not juts primitives). I don't understand why this can't be used for attributes. – wingerse Oct 29 '17 at 13:29
20

I have the same problem. I consider to use strings. This is not type-safe, but it's readable and I think we will be able to write valid numbers in strings :-).

class BlahAttribute : Attribute
{
  private decimal value;

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

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

It's not a beauty, but after considering all the options, it's good enough.

Stefan Steinegger
  • 63,782
  • 15
  • 129
  • 193
  • 1
    Looks like that's how mbUnit copes http://vkreynin.wordpress.com/2007/05/25/mbunit-24-rtm-now-you-can-use-decimals-in-row-attributes/ – Andy Dent May 27 '10 at 08:31
2

When I have run into this situation, I ended up exposing the properties on the attribute as a Double, but inside the attribute treated them like Decimal. Far from perfect, but for the simple cases, it just might be what you need.

ckittel
  • 6,478
  • 3
  • 41
  • 71
1

For realtime tricks with attributes i am using TypeConverter class.

Avram
  • 4,267
  • 33
  • 40
-1

You can use the following constructor. When you have a decimal literal in C# code, the C# compiler emits a call to this constructor.

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

Edit: I know this is not convenient.

Sam Harwell
  • 97,721
  • 20
  • 209
  • 280
  • 5
    If this worked in an attribute, then I'm guessing simply using the "m" suffix would too, but neither does (Using System.ComponentModel.DefaultValueAttribute as my test) – xr280xr Jun 01 '15 at 17:48