In .Net, why aren't attributes declared on interfaces returned when calling Type.GetCustomAttributes(true)?

1k Views Asked by At

In answer to this question I tried to use Type.GetCustomAttributes(true) on a class which implements an interface which has an Attribute defined on it. I was surprised to discover that GetCustomAttributes didn't return the attribute defined on the interface. Why doesn't it? Aren't interfaces part of the inheritance chain?

Sample code:

[Attr()]
public interface IInterface { }

public class DoesntOverrideAttr : IInterface { }

class Program
{
    static void Main(string[] args)
    {
        foreach (var attr in typeof(DoesntOverrideAttr).GetCustomAttributes(true))
            Console.WriteLine("DoesntOverrideAttr: " + attr.ToString());
    }
}

[AttributeUsage(AttributeTargets.All, Inherited = true)]
public class Attr : Attribute
{
}

Outputs: Nothing

2

There are 2 best solutions below

2
On BEST ANSWER

I don't believe attributes defined on implemented interfaces can be reasonably inherited. Consider this case:

[AttributeUsage(Inherited=true, AllowMultiple=false)]
public class SomethingAttribute : Attribute {
    public string Value { get; set; }

    public SomethingAttribute(string value) {
        Value = value;
    }
}

[Something("hello")]
public interface A { }

[Something("world")]
public interface B { }

public class C : A, B { }

Since the attribute specifies that multiples are not allowed, how would you expect this situation to be handled?

0
On

Because the type DoesntOverrideAttr doesn't have any custom attributes. The Interface that it implements does (remember, a class doesn't inherit from an interface...it implements it so getting attributes up the inheritance chain still won't include attributes from interfaces):

// This code doesn't check to see if the type implements the interface.
// It should.
foreach(var attr in typeof(DoesntOverrideAttr)
                        .GetInterface("IInterface")
                        .GetCustomAttributes(true))
{
    Console.WriteLine("IInterface: " + attr.ToString());
}