[[
target
:]?
attribute-name
(
|
positional-param + | |
[
named-param
=
expression
] + | |
positional-param
+ , [
named-param
=
expression
]
+
)?]
|
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 that it derives from, or a
parameter can specify how its values are to be passed with modifiers
such as the ref
modifier in C#. The limitation of
this approach is that you can only associate information with code
elements using the predefined constructs that the language itself
provides.
Attributes allow programmers to add to 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 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 on an
element, the attribute name is the name of the type. By convention
the derived type name ends with the word “Attribute”, but
this suffix isn’t required.
In this example we specify that the Foo
class is
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 typename, as follows:
[System.SerializableAttribute] public class Foo {...}
The preceding two examples that use the
Serializable
attribute are semantically identical.
The C# language and the BCL include a number of predefined attributes. For more information on the other attributes included in the BCL, and on creating your own attributes, see Section 3.11 in Chapter 3.
Attributes can take parameters, which specify additional information on the code element beyond the mere presence of the attribute.
In this next example, we specify that the class
Foo
is obsolete using the
Obsolete
attribute. This attribute allows you to
include parameters that specify a message and indicate 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 parameters. 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 one of 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 on the attribute type.
When specifying an attribute on an element, positional parameters are mandatory, and named parameters are optional.
Since the parameters used when specifying 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. Sometimes it is necessary to explicitly specify that the attribute applies to a particular target.
In the beta 1 version of the C# compiler, the valid targets are
assembly
and
module
. In future versions of the language,
this list of explicit targets is expected to expand to include
parameters, return values, etc.
Here is an example that uses the CLSCompliant
attribute to specify the level of CLS compliance for an entire
assembly:
[assembly:CLSCompliant(true)]
You can specify multiple attributes on 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 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 {...}
3.144.90.182