none
C# attribute parameter type: does it allow another Attribute?

    Question

  • Hi,

    I am a developer interested in working with C#. The feature I'm interested in is Attribute (called annotation in Java).

    My question is: Does attribute parameter type support the use of another Attribute?

    In Section 17.1.3 of the C# language specification, it states the followings:

    "...

    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 (§17.2).
    • Single-dimensional arrays of the above types.

    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.

    ..."

    I am curious whether the second type (type object) also means that Attribute can be used. Because, as far as I know Object is the supertype of all referenced types (?).

    To illustrate, I want to achieve something like the following:

    [ MyAttribute( "abc", p1="...", p2=[ AnotherAttribute("123") ] ) ]

    class MyClass {  ... }

    where: MyAttribute and AnotherAttribute are attributes, and parameter MyAttribute.p2 is declared with the type AnotherAttribute.

    Thank you very much in advance for your response.

    Tuesday, May 2, 2017 1:45 AM

All replies

  • There's another piece of documentation that actually specifies this in more detail (https://msdn.microsoft.com/en-us/library/aa288454(v=vs.71).aspx):

    Attribute parameters are restricted to constant values of the following types:
    • Simple types (bool, byte, char, short, int, long, float, and double)
    • string
    • System.Type
    • enums
    • object (The argument to an attribute parameter of type object must be a constant value of one of the above types.)
    • One-dimensional arrays of any of the above types

    So going by this, I would say the answer to your question is no, you cannot do that. Even though you can declare an attribute parameter as type object, the actual argument you pass in must still be a constant string, bool, etc (declaring it as an object just means you can use any of these types each time you declare the attribute).

    It may help if you stated what you are trying to achieve, because the typical situation is you would just place both attributes on the class. E.g.:

    [MyAttribute("abc")]
    [AnotherAttribute("123")]
    class MyClass {...}

    Tuesday, May 2, 2017 7:10 AM
  • The nested attribute declaration like you're trying to do won't work for reasons RJP1973 mentioned. However that doesn't mean you cannot chain attributes. The preferred approach is to use inheritance. But there are several attributes that accept a Type as a parameter. They do this so they can create an instance of the type at runtime. It isn't clean but it does work. Take a look at DefaultValue as an example.

    Do you have a practical example where this makes sense? I cannot think of a situation where chaining attributes like this really makes sense outside of a workaround for not having generic attribute support. I suspect most scenarios where this may look like a good idea has better solutions.

    Michael Taylor
    http://www.michaeltaylorp3.net

    Tuesday, May 2, 2017 2:13 PM
    Moderator