1

In C#, one can use reflection to obtain the attributes on a member m via m.CustomAttributes (see the documentation for this property). However, this approach seems to miss three custom attributes on the GetType method of Object (see the Object in the Reference Source for .NET Framework 4.6.1):

using System;
using System.Linq;
namespace ConsoleApplication1 {
  public class Program {
    public static void Main(string[] args) {
      var desiredCustomAttributes = typeof(object)
        .GetMethods()
        .First(m => m.Name == "GetType")
        .CustomAttributes
        .Select(ca => ca.ToString())
        .Where(s =>
          s.Contains("Pure") ||
          s.Contains("ResourceExposure") ||
          s.Contains("MethodImplAttribute"));
      var n = desiredCustomAttributes.Count();
      Console.WriteLine("Expected: 3");
      Console.WriteLine("  Actual: " + n); // prints "  Actual: 0"
      Console.ReadKey();
    }
  }
}

Why do these three custom attributes not show up?

Maybe it has something to do with the fact that it is an external method?

Actually, being external has nothing to do with it.

using System;
using System.Linq;
using System.Runtime.Versioning;
namespace ConsoleApplication1 {
  public class ResourceExposureAttributeOnConstructor {
    [ResourceExposure(ResourceScope.None)]
    public ResourceExposureAttributeOnConstructor() { }
  }
  public class Program {
    public static void Main(string[] args) {
      var n = typeof(object)
        .GetConstructors()
        .First()
        .CustomAttributes
        .Select(ca => ca.ToString())
        .Where(s => s.Contains("ResourceExposure"))
        .Count();
      Console.WriteLine("Expected: 1");
      Console.WriteLine("  Actual: " + n); // prints "  Actual: 0"
      Console.ReadKey();
    }
  }
}
Tyson Williams
  • 1,630
  • 15
  • 35

1 Answers1

1

It's not because the method is external. Tried with a user defined class:

class MyAttr : Attribute { }
class Program
{
    [Pure]
    [ResourceExposure(ResourceScope.AppDomain)]
    [MethodImpl]
    [MyAttr]
    public void Foo() { }
}

.CustomAttributes returns MyAttr only. I think it's simply because FCL don't threat the three attributes as custom attributes. Looking into the source code, MethodInfo.CustomAttributes finally invokes MetadataImport.EnumCustomAttributes, where an external method is called.

[SecurityCritical]
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern void _Enum(IntPtr scope, int type, int parent, out MetadataEnumResult result);

I didn't debug into it, but I think it makes sense that this method knows some built-in attributes and excludes them from custom attributes.

EDIT PureAttribute and ResourceExposureAttribute are conditionally built, that's why you can't get them.

[Conditional("RESOURCE_ANNOTATION_WORK")]
public sealed class ResourceExposureAttribute : Attribute

[Conditional("CONTRACTS_FULL")]
public sealed class PureAttribute : Attribute

It seems that MethodImplAttribute is special.

Cheng Chen
  • 42,509
  • 16
  • 113
  • 174
  • What does it mean for an attribute to be "built-in"? One custom attribute that is returned from `GetType` is `__DynamicallyInvokable` (cf. [this SE Q&A](http://stackoverflow.com/questions/12550749/what-is-the-dynamicallyinvokable-attribute-for)). The fact that this custom attribute shows up in the list but is _not_ in the source suggests to me that it is more "built-in" than these other three. – Tyson Williams Dec 14 '15 at 07:21
  • So suppose that the actual behavior is the expected behavior. Then how can one know what types of custom attributes will be returned from a call to `CustomAttributes` and what types will not? – Tyson Williams Dec 14 '15 at 07:22
  • @TysonWilliams I mean, the definition of `custom attribute` is made by FCL. Obviously user-defined attributes are custom. But built-in attributes are not guaranteed. – Cheng Chen Dec 14 '15 at 07:26
  • @TysonWilliams I'm afraid you can't find an official list of custom attributes rule. Just curious, why do you need to know if a built-in attribute is custom or not? – Cheng Chen Dec 14 '15 at 07:27
  • Trying to infer dependencies of a given type. `Object` is clearly dependent on these three attributes. Someone compiled `mscorelib`, which of course includes `Object`. The compiler needs to know that `Object` is dependent on these three types. How does it do that? – Tyson Williams Dec 14 '15 at 07:40
  • @TysonWilliams Here what's the meaning of `dependent on sth`? It's just like you define two classes A and B in the same assembly, B derives from A, and A has one property whose type is B. I don't see anything wrong. – Cheng Chen Dec 14 '15 at 07:45
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/97826/discussion-between-tyson-williams-and-danny-chen). – Tyson Williams Dec 14 '15 at 07:48