Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Attribute argument must be a constant error when using an optional parameter in the attribute constructor

Can anyone explain why this code works:

public class AdministratorSettingValidationAttribute : Attribute
{
    public AdministratorSettingValidationAttribute(AdministratorSettingDataType administratorSettingDataType)
    {
        DataType = administratorSettingDataType;
    }

    public AdministratorSettingValidationAttribute(AdministratorSettingDataType administratorSettingDataType, Type enumerationType)
    {
        DataType = administratorSettingDataType;
        EnumerationType = enumerationType;
    }
}

...but refactoring it to use an optional parameter instead:

    public AdministratorSettingValidationAttribute(AdministratorSettingDataType administratorSettingDataType, Type enumerationType = null)
    {
        DataType = administratorSettingDataType;
        EnumerationType = enumerationType;
    }

...causes a compile time error: "An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type".

like image 598
Jonathan Moffatt Avatar asked Nov 28 '11 02:11

Jonathan Moffatt


2 Answers

UPDATE

The bug was reported in July of last year and is already fixed. The fix will appear in the next version of C#. See this Connect feedback item for details:

http://connect.microsoft.com/VisualStudio/feedback/details/574497/optional-parameter-of-type-string-in-a-attribute-constructor-cannot-be-null


That's clearly a compiler bug. Thanks for bringing it to my attention.

What is supposed to happen here is the compiler is supposed to realize that the optional value expression is implicitly converted to the formal parameter type, and then treat the expression as a constant expression of that type. What it is actually doing is treating the expression as the typeless null literal, which is wrong.

You can work around the bug by turning the constant into an explicitly typed one:

public AdministratorSettingValidationAttribute(AdministratorSettingDataType administratorSettingDataType, Type enumerationType = (Type)null) 

The fix is probably straightforward but I cannot promise that the fix will be in the next version of C#; I'm not sure what the schedule is like for taking non-critical bug fixes at this point.

Thanks again, and apologies for the inconvenience.

like image 65
Eric Lippert Avatar answered Nov 18 '22 03:11

Eric Lippert


This smells like a compiler bug to me. Attribute classes are 'special' classes in a way that they can be used as meta data. The C# compiler allows you to use them differently then normal classes and therefore we can assume that a (partial) custom implementation for compiling usage of attribute classes exists in the C# compiler. (Can anyone test this on mono?)

That said, i did some tests and found that only when using the constructor of an attribute which specifies the default value of a parameter as null without defining a custom value of that attribute, the compiler gives us an error. My test code:

class TestAttribute : Attribute
{
    public TestAttribute(object test = null) { }
    //public TestAttribute(int test = 0) { } 

    public void TestMethod(object test = null) { }
}

class TestClass
{
    public TestClass(object test  = null) { }
}

[Test()] // crashes
//[Test()] // Works when using the constructor taking an int
//[Test(null)] // works
class Program
{
    static void Main(string[] args)
    {
        TestClass t = new TestClass(); // works

        TestAttribute a = typeof(Program).GetCustomAttributes(typeof(TestAttribute), false).Cast<TestAttribute>().First();

        a.TestMethod(); // works
    }
}

(Tested with VS 2010 under .NET 4.0, can anyone test this with mono?)

Note that Attributes already allow you to address properties as if they were optional, so you could make your optional parameter a property (if not already, and remove it from the constructor. This still allows you to write [Test(null, MyProperty = null)]

like image 29
Polity Avatar answered Nov 18 '22 03:11

Polity