Page 1 of 6
The role of custom attributes in C# can be confusing. They are easy to use when supplied, but how do you go about creating custom attributes? And when are they useful?
Attributes - they really don't seem to be necessary as part of a programming language. After all why "decorate" code with attributes when you can achieve the same results by more direct routes? In nearly all cases an attribute is an excuse for not implementing a property that does the same job.
However attributes provide a useful extension to the standard language syntax and a way of adding features after the event and without having to extensively re-work the classes that that attributes are applied to. In other words, the classes that you apply attributes to don't necessarily need to know anything about the attributes you apply. In this sense attributes have been likened to "code patching" brought up-to-date. You can use an attribute to add a behaviour without modifying the core code and you can take this behavior away just as easily.
C# has supported and usefully employed attributes for some time but there is still a great deal of confusion about when custom attributes might or might not be useful.
In .NET an attribute is an item of data associated with a programming construct that is stored in the assembly and which can be accessed by the use of reflection. Notice that some confusion is caused by the fact that some built-in attributes also additionally affect the way that the compiler seems to work. In the main this is not something that most attributes, and certainly not custom attributes, do.
Essentially a custom attribute is a "code comment" that gets compiled into your code, as metadata, and which other code, including you own, can retrieve and possibly act on.
This is the standard explanation of an attribute but the attribute mechanism is so much more.
- When you retrieve an attribute an instance of a class that represents the attribute is created.
Understanding how this mechanism works means that you can think about exactly how attributes might be useful and how things can go wrong.
There is a sense in which an attribute can always be replaced by a property. For example, you might mark a class as using ASCII encoding for its text and hence implement an [ASCII] attribute. Any other class that make use of a class so marked would have to inspect it to discover that it was ASCII and then arrange to treat it correctly.
It should be fairly obvious that an alternative is to use an ASCII property set to True or False to indicate the same information. Notice that the two approaches have some similarities and some differences:
- Any client that uses the class has to implement retrieving and testing the attribute or the property and act accordingly – that is, nothing is enforced in either approach.
- A property can be set at compile time and can be changed at run time. An attribute on the other hand is set at compile time and generally isn’t changed at runtime.
- A property is associated with instances of a class but an attribute can be associated with many different entities including classes, methods, parameters and so on.
- Attributes don’t change and can be associated with a range of entities
This seems to sum up the situation but notice that with such a flexible implementation you can always change the way things work. This is the standard and most appropriate way of working with attributes.
Implementing a custom attribute
Implementing a custom attribute such as [ASCII], mentioned in the previous section, is fairly easy as long as you don’t read into it more than there is.
All you have to do is create a class that inherits from Attribute:
public class ASCIIattribute : Attribute
It is usual to use a name of the form Xattribute and if you do the system will treat the names X and Xattribute as the same.
Unfortunately if you do declare the class as Xattribute, e.g. ASCIIattribute, then IntelliSense prompts with the full name. Personally I’d rather keep attribute names short and meaningful so I prefer:
public class ASCII : Attribute
Now you can apply the attribute to any class as in:
public class MyClass
Of course nothing happens if you do this but it is legal syntax – now to give it some semantics.