Search code examples
c#.netattributeusage

C#: AttributeUsage behaving strange on inherited Attributes - Is this intended behaviour?


I'm working with custom attributes, which again have a common base class. The AttributeUsage attribute is declared on the base attribute class, not on the concrete attribute classes. My attribute usage on the base class says AttributeTargets.Class, AllowMultiple = true, Inherited = true

Now when i'm working with my concrete attribute classes they use the AttributeUsage settigs from the base attribute class for Target and AllowMultiple, but not for Inherited -> this does not make any sense for me.

Here's a little code example which does not output what i expect:

[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
public abstract class TestAttributeBase : Attribute
{
}

public class TestAttribute : TestAttributeBase
{
    public string Value {get; private set;}
    
    public TestAttribute(string value)
    {
        Value = Value;  
    }
}

[TestAttribute("A")]
public class A {
}

[TestAttribute("B")]
[TestAttribute("C")]
public class B : A
{
}

public static void Main()
{
    var customAttributes = typeof(B).GetCustomAttributes<TestAttributeBase>(true).ToList();
    Console.WriteLine(customAttributes.Count);
}

Here's the dotnetfiddle Link with the same code: https://dotnetfiddle.net/BZ7R4S

If you run this code it outputs "2", but i would expect "3". The [AttributeUsage] of TestAttributeBase is definetly inherited to the TestAttribute, because if you change AttributeTargets.Class to e.g. AttributeTargets.Field, the code does not compile. If you set AllowMultiple to false the code does not compile -> I discern from this that [AttributeUsage] gets inherited to the concrete Attribute classes, but not the Inherited property.

Does this make any sense?

If i add the exact same [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)] to the concrete TestAttribute, it works and ouputs 3


Solution

  • The issue was posted closed as "won't fix" with the following comment:

    Even it sounds like a bug fixing this now probably quite breaking as it was like this from the beginning. Given that there is a workaround: add your own [AttributeUsage] instead of assuming the base class's will be used closing the issue as not planned

    So the only option is to apply the attribute to the derived class:

    [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
    public class TestAttribute : TestAttributeBase
    {
        // ...
    }