Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GetCustomAttributes vs GetCustomAttributesData

I'm trying to figure out the best way to get custom attributes from a property. I've been using GetCustomAttributes() for this but I've recently read that GetCustomAttributes() causes an instance of the attribute to be created and GetCustomAttributesData() just gets data about the attribute without having to create an instance of the attribute.

With this in mind, it seems like GetCustomAttributesData() should be faster because it doesn't create an instance of the attribute. However, I'm not seeing this expected result in tests. When looping through the properties in a class, the first iteration has GetCustomAttributes() running about 6ms and GetCustomAttributesData() running about 32ms.

Does anyone know why it takes GetCustomAttributesData() longer to run?

My primary goal is to test for the existence of an attribute and ignore any property containing this attribute. I don't particularly care which method I end up using and I'm not really concerned with what either method returns apart from understanding why GetCustomAttributesData() is slower than GetCustomAttributes().

Here's some sample code I used to test with. I tested each of these if statements independently by commenting out one and then the other.

public static void ListProperties(object obj)
{
    PropertyInfo[] propertyInfoCollection = obj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);

    foreach (PropertyInfo prop in propertyInfoCollection)
    {
        // This runs around 6ms on the first run
        if (prop.GetCustomAttributes<MyCustomAttribute>().Count() > 0)
            continue;

        // This runs around 32ms on the first run
        if (prop.GetCustomAttributesData().Where(x => x.AttributeType == typeof(MyCustomAttribute)).Count() > 0)
            continue;

        // Do some work...
    }
}

public class MyCustomAttribute : System.Attribute
{
}

Just a little while ago, I decided to try the IsDefined() method after reading this post. It seems to be faster than both GetCustomAttributes() and GetCustomAttributesData().

if (prop.IsDefined(typeof(MyCustomAttribute)))
    continue;
like image 392
jmac Avatar asked Nov 08 '17 16:11

jmac


1 Answers

Well GetCustomAttributesData also creates instances of new objects, just not of the attributes themselves. It creates instances of CustomAttributeData. This class has mainly information about the attribute type but also about the constructor and the constructor arguments and even the names of the constructor arguments.

These properties have to be set using reflection wheras creating the attribute instance is just a standard object creation. Of course it all depends on how complex the constructor of your attribute is, although in general I have rarely seen complex attributes.

Thus calling GetCustomAttributesData gives you more/different information about the attribute than GetCustomAttributes but is (for simple attributes) a more costly operation.

However if you intend to call GetCustomAttributesData multiple times on the same MemberInfo object it could be faster since reflection calls are usually cached. But I didn't run a benchmark on this, so take it with a pinch of salt.

like image 144
Peter Avatar answered Sep 30 '22 16:09

Peter