48

Here is my custom attribute and a class I'm using it on:

[MethodAttribute(new []{new MethodAttributeMembers(), new MethodAttributeMembers()})]
public class JN_Country
{

}

public class MethodAttribute : Attribute
{
    public MethodAttributeMembers[] MethodAttributeMembers { get; set; }

    public MethodAttribute(MethodAttributeMembers[] methodAttributeMemberses)
    {
        MethodAttributeMembers = methodAttributeMemberses;
    }
}

public class MethodAttributeMembers
{
    public string MethodName { get; set; }
    public string Method { get; set; }
    public string MethodTitle { get; set; }
}

The syntax error, displayed on the first line above:

An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type

Why does this error occur?

ericArbour
  • 579
  • 8
  • 12
Football-Is-My-Life
  • 1,407
  • 7
  • 18
  • 35

3 Answers3

47

This supplements the information Simon already gave.

I found some documentation here: Attribute parameter types:

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. (emphasis added by me)

A constructor argument or public field which does not have one of these types, cannot be used as a positional or named parameter in an attribute specification.

The last bullet point explains your syntax error. You've defined a one-dimensional array, but it should only be of primitive types, string, etc. as listed in the previous bullet points.

redcalx
  • 8,177
  • 4
  • 56
  • 105
Grant Winney
  • 65,241
  • 13
  • 115
  • 165
27

Attribute arguments must be compile-time constant. That means that the compiler must be able to "bake in" the values of the arguments when the assembly is compiled. new ReferenceType() is not constant - it must be evaluated at runtime to determine what it is.

Interestingly, this is a little bit flimsy in that there are some edge cases to that rule. Other than those though, you cannot do what you're trying to do.

Simon Whitehead
  • 63,300
  • 9
  • 114
  • 138
0

Let me add that the compiler can return this error without any particular file or line of code, if your attribute has a constructor that has a parameter that isn't a simple type and you use the constructor (i.e. your non-simple parameter has a default value).

[MyAttribute(MySimpleParameter: "Foo")]
public class MyObject
{

}

public class MyAttribute : Attribute
{
    public string MySimpleProperty { get; set; }

    public MyPropertyClass MyComplexProperty { get; set; }

    public MethodAttribute(string MySimpleParameter, MyPropertyClass MyComplexParameter = null)
    {
        MySimpleProperty = MySimpleParameter;
        MyComplexProperty = MyComplexParameter;
    }
}

public class MyPropertyClass
{
    public string Name { get; set; }
    public string Method { get; set; }
}
jahu
  • 5,427
  • 3
  • 37
  • 64