[[target
:]?attribute-name
(positional-param
+ | [named-param
=expr
]+ |positional-param
+, [named-param
=expr
]+)?]
Attributes are language constructs that can decorate a code element (assemblies, modules, types, members, return values, and parameters) with additional information.
In every language, you specify information associated with the types,
methods, parameters, and other elements of your program. For example,
a type can specify a list of interfaces it derives from, or a
parameter can specify modifiers, such as the ref
modifier in C#. The limitation of this approach is you can associate
information with code elements using only the predefined constructs
that the language provides.
Attributes allow programmers to extend the types of information associated with these code elements. For example, serialization in the .NET Framework uses various serialization attributes applied to types and fields to define how these code elements are serialized. This approach is more flexible than requiring the language to have special syntax for serialization.
An attribute is defined
by a class that inherits (directly or
indirectly) from the abstract class
System.Attribute
. When specifying an attribute to
an element, the attribute name is the name
of the type. By convention, the derived
type name ends in Attribute
, although specifying
the suffix is not required when specifying the attribute.
In this example, the Foo
class is specified as
serializable using the Serializable
attribute:
[Serializable] public class Foo {...}
The Serializable
attribute is actually a type
declared in the System
namespace, as follows:
class SerializableAttribute : Attribute {...}
We could also specify the Serializable
attribute
using its fully qualified type name, as follows:
[System.SerializableAttribute] public class Foo {...}
The preceding two examples of using the
Serializable
attribute are semantically identical.
The C# language and the FCL include a number of predefined attributes. For more information about the other attributes included in the FCL and creating your own attributes, see Chapter 14.
Attributes can take parameters, which can specify additional information on the code element beyond the mere presence of the attribute.
In this example, the class Foo
is specified as
obsolete using the Obsolete
attribute. This
attribute allows parameters to be included to specify both a message
and whether the compiler should treat the use of this class as an
error:
[Obsolete("Use Bar class instead", IsError=true)] public class Foo {...}
Attribute parameters fall into one of two categories: positional and
named. In the preceding example, Use Bar class instead
is a positional parameter and
IsError=true
is a named parameter.
The positional parameters for an attribute correspond to the parameters passed to the attribute type’s public constructors. The named parameters for an attribute correspond to the set of public read-write or write-only instance properties and fields of the attribute type.
When specifying an attribute of an element, positional parameters are mandatory and named parameters are optional. Since the parameters used to specify an attribute are evaluated at compile time, they are generally limited to constant expressions.
Implicitly, the target of an attribute is the code element it immediately precedes, such as with the attributes we have covered so far. Sometimes it is necessary to explicitly specify that the attribute applies to particular target.
Here is an example of using the CLSCompliant
attribute to specify the level of CLS compliance for an entire
assembly:
[assembly:CLSCompliant(true)]
Multiple attributes can be specified for a single code element. Each attribute can be listed within the same pair of square brackets (separated by a comma), in separate pairs of square brackets, or in any combination of the two.
Consequently, the following three examples are semantically identical:
[Serializable, Obsolete, CLSCompliant(false)] public class Bar {...} [Serializable] [Obsolete] [CLSCompliant(false)] public class Bar {...} [Serializable, Obsolete] [CLSCompliant(false)] public class Bar {...}
Get C# in a Nutshell, Second Edition now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.