Why "decimal" is not a valid attribute parameter type?

C#.NetAttributes

C# Problem Overview


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.

C# Solutions


Solution 1 - C#

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

Taken from this answer by 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.

Solution 2 - C#

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. > - The type object. > - The 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.

Solution 3 - C#

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;

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionCheng ChenView Question on Stackoverflow
Solution 1 - C#djdd87View Answer on Stackoverflow
Solution 2 - C#KobiView Answer on Stackoverflow
Solution 3 - C#Daniel BarbalaceView Answer on Stackoverflow