More C# Attribute annoyances

And on the subject of the deficiencies of attributes, there are a few more things I’d like to accomplish, but cant.  First on the list, generic attributes:

// Boo C# compiler, boo!!!
public class GenericAttribute<T> : Attribute

So many times I’d like to have some kind of generic attribute, whether for validation, for action filters, the list goes on and on:

error CS0698: A generic type cannot derive from 'Attribute' because it is an attribute class

Well that’s helpful!  It gets worse.  Let’s try a more interesting attribute value for an attribute that takes a value in its constructor:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class FineThenAttribute : Attribute
    public FineThenAttribute(int value)

Most of the time, I’ll put a hard-coded value into the constructor.  Sometimes, I’d like for that value to come from…somewhere else:

public class PrettyPlease
    public const int Five = 5;
    public static int Four = 4;

    public void Method()

The first two compile just fine, as the values passed in are constant values.  The third attribute does NOT compile, however.  I get yet another roadblock:

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

One time I tried to get extra fancy with attribute decorators.  Silly me!  This attribute definition compiles just fine:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class DelegateTypeAttribute : Attribute
    public DelegateTypeAttribute(Action jackson)

But it’s impossible to use!  None of these attribute declarations compile:

public class WithACherryOnTop
    [DelegateType(() => { })]
    [DelegateType(new Action(MatchesAction))]
    public void Method()

    private static void MatchesAction()

Blech.  Every time I try and do something mildly interesting with attributes, blocked by the CLR!

About Jimmy Bogard

I'm a technical architect with Headspring in Austin, TX. I focus on DDD, distributed systems, and any other acronym-centric design/architecture/methodology. I created AutoMapper and am a co-author of the ASP.NET MVC in Action books.
This entry was posted in C#. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • I agree with most of your complaints, but it makes sense to me that attribute arguments must be constants. Attribute instantiation is completely transparent – if an attribute is initialized from a mutable field, how can I reason effectively about what its value will be?

  • @Paul

    We do have some insight into *when* an attribute is instantiated – it’s when you query type/member info for its custom attributes. Maybe it’s from the fact that you can’t guarantee immutability after compilation for anything but a few special cases.

  • @jimmy – A lot of the time we end up with an attribute that just takes a Type and we do all the crazy stuff outside the scope of the attribute.

    public FormSubType FormSubType { get; set; }

    The code that uses the attribute can ask it to create an instance of that type. At that point we check if it’s the right type and create and instance of it and return it. The disadvantage is that we don’t get compile time checking for the type but that really hasn’t been a problem.

  • Feeling your pain the Action one – passing a delegate would be fantastic eh!

  • Damien

    > passing a delegate would be fantastic eh!


    Best way I’ve found to get around this is pass in an array of enums, each mapped to an anonymous function.

  • Mark

    It might be worth reading this article about dynamic attributes in c:

  • Pingback: [WTF] Generic attributes in C# | mnaoumov.NET()

  • Pingback: Generic Attributes in C# | Whathecode()

  • cosmin

    In C# attributes are designed for metadata. The face that we use them now for runtime features is wrong usage. CLI Metadata are included in the compiled code, so, it is absolutely normal to require values available at compile time.