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

Cheng Chen picture Cheng Chen · Jul 7, 2010 · Viewed 38.9k times · Source

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.

Answer

djdd87 picture djdd87 · Jul 7, 2010

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.