# Attributes

System.Attribute is a base class used to define custom attributes.

Attributes are annotations that can be added to programming elements such as assemblies, types, members, and parameters. They are stored in the metadata of the assembly and can be accessed at runtime using the reflection APIs. For example, the Framework defines the ObsoleteAttribute, which can be applied to a type or a member to indicate that the type or member has been deprecated.

Attributes can have one or more properties that carry additional data related to the attribute. For example, ObsoleteAttribute could carry additional information about the release in which a type or a member got deprecated and the description of the new APIs replacing the obsolete API.

Some properties of an attribute must be specified when the attribute is applied. These are referred to as the required properties or required arguments, because they are represented as positional constructor parameters. For example, the ConditionString property of the ConditionalAttribute is a required property.

Properties that do not necessarily have to be specified when the attribute is applied are called optional properties (or optional arguments). They are represented by settable properties. Compilers provide special syntax to set these properties when an attribute is applied. For example, the AttributeUsageAttribute.Inherited property represents an optional argument.

✓ DO name custom attribute classes with the suffix "Attribute."

✓ DO apply the AttributeUsageAttribute to custom attributes.

✓ DO provide settable properties for optional arguments.

✓ DO provide get-only properties for required arguments.

✓ DO provide constructor parameters to initialize properties corresponding to required arguments. Each parameter should have the same name (although with different casing) as the corresponding property.

X AVOID providing constructor parameters to initialize properties corresponding to the optional arguments.

In other words, do not have properties that can be set with both a constructor and a setter. This guideline makes very explicit which arguments are optional and which are required, and avoids having two ways of doing the same thing.