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;

    [FineThen(6)]
    [FineThen(Five)]
    [FineThen(Four)]
    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(MatchesAction)]
    [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!

Related Articles:

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

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.
  • http://paulbatum.blogspot.com Paul Batum

    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?

  • http://www.lostechies.com/members/bogardj/default.aspx bogardj

    @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.

  • http://www.lostechies.com/members/rhouston/default.aspx Ray Houston

    @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.

    [ValueConverter(typeof(EnumValueConverter
    ))]
    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.

  • http://neilmosafi.blogspot.com Neil Mosafi

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

  • Damien

    > passing a delegate would be fantastic eh!

    Totally.

    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:
    http://geekswithblogs.net/abhijeetp/archive/2009/01/10/dynamic-attributes-in-c.aspx

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

  • Pingback: Generic Attributes in C# | Whathecode