|
| 1 | +--- |
| 2 | +title: "C# reserved attributes: Conditional, Obsolete, AttributeUsage" |
| 3 | +ms.date: 04/09/2020 |
| 4 | +description: These attributes are interpreted by the compiler to affect the code generated by the compiler |
| 5 | +--- |
| 6 | +# Reserved attributes: ConditionalAttribute, ObsoleteAttribute, AttributeUsageAttribute |
| 7 | + |
| 8 | +These attributes can be applied to elements in your code. They add semantic meaning to those elements. The compiler uses those semantic meanings to alter its output and report possible mistakes by developers using your code. |
| 9 | + |
| 10 | +## `Conditional` attribute |
| 11 | + |
| 12 | +The `Conditional` attribute makes the execution of a method dependent on a preprocessing identifier. The `Conditional` attribute is an alias for <xref:System.Diagnostics.ConditionalAttribute>, and can be applied to a method or an attribute class. |
| 13 | + |
| 14 | +In the following example, `Conditional` is applied to a method to enable or disable the display of program-specific diagnostic information: |
| 15 | + |
| 16 | +::::::code language="csharp" source="snippets/trace.cs" interactive="try-dotnet" ::: |
| 17 | + |
| 18 | +If the `TRACE_ON` identifier isn't defined, the trace output isn't displayed. Explore for yourself in the interactive window. |
| 19 | + |
| 20 | +The `Conditional` attribute is often used with the `DEBUG` identifier to enable trace and logging features for debug builds but not in release builds, as shown in the following example: |
| 21 | + |
| 22 | +::::::code language="csharp" source="snippets/ConditionalExamples.cs" id="SnippetConditional" ::: |
| 23 | + |
| 24 | +When a method marked conditional is called, the presence or absence of the specified preprocessing symbol determines whether the call is included or omitted. If the symbol is defined, the call is included; otherwise, the call is omitted. A conditional method must be a method in a class or struct declaration and must have a `void` return type. Using `Conditional` is cleaner, more elegant, and less error-prone than enclosing methods inside `#if…#endif` blocks. |
| 25 | + |
| 26 | +If a method has multiple `Conditional` attributes, a call to the method is included if at one or more conditional symbols is defined (the symbols are logically linked together by using the OR operator). In the following example, the presence of either `A` or `B` results in a method call: |
| 27 | + |
| 28 | +::::::code language="csharp" source="snippets/ConditionalExamples.cs" id="SnippetMultipleConditions" ::: |
| 29 | + |
| 30 | +### Using `Conditional` with attribute classes |
| 31 | + |
| 32 | +The `Conditional` attribute can also be applied to an attribute class definition. In the following example, the custom attribute `Documentation` will only add information to the metadata if `DEBUG` is defined. |
| 33 | + |
| 34 | +::::::code language="csharp" source="snippets/ConditionalExamples.cs" id="SnippetConditionalConditionalAttribute" ::: |
| 35 | + |
| 36 | +## `Obsolete` attribute |
| 37 | + |
| 38 | +The `Obsolete` attribute marks a code element as no longer recommended for use. Use of an entity marked obsolete generates a warning or an error. The `Obsolete` attribute is a single-use attribute and can be applied to any entity that allows attributes. `Obsolete` is an alias for <xref:System.ObsoleteAttribute>. |
| 39 | + |
| 40 | +In the following example the `Obsolete` attribute is applied to class `A` and to method `B.OldMethod`. Because the second argument of the attribute constructor applied to `B.OldMethod` is set to `true`, this method will cause a compiler error, whereas using class `A` will just produce a warning. Calling `B.NewMethod`, however, produces no warning or error. For example, when you use it with the previous definitions, the following code generates two warnings and one error: |
| 41 | + |
| 42 | +::::::code language="csharp" source="snippets/ObsoleteExample.cs" interactive="try-dotnet" ::: |
| 43 | + |
| 44 | +The string provided as the first argument to the attribute constructor will be displayed as part of the warning or error. Two warnings for class `A` are generated: one for the declaration of the class reference, and one for the class constructor. The `Obsolete` attribute can be used without arguments, but including an explanation what to use instead is recommended. |
| 45 | + |
| 46 | +## `AttributeUsage` attribute |
| 47 | + |
| 48 | +The `AttributeUsage` attribute determines how a custom attribute class can be used. <xref:System.AttributeUsageAttribute> is an attribute you apply to custom attribute definitions. The `AttributeUsage` attribute enables you to control: |
| 49 | + |
| 50 | +- Which program elements attribute may be applied to. Unless you restrict its usage, an attribute may be applied to any of the following program elements: |
| 51 | + - assembly |
| 52 | + - module |
| 53 | + - field |
| 54 | + - event |
| 55 | + - method |
| 56 | + - param |
| 57 | + - property |
| 58 | + - return |
| 59 | + - type |
| 60 | +- Whether an attribute can be applied to a single program element multiple times. |
| 61 | +- Whether attributes are inherited by derived classes. |
| 62 | + |
| 63 | +The default settings look like the following example when applied explicitly: |
| 64 | + |
| 65 | +:::code language="csharp" source="snippets/NewAttribute.cs" id="SnippetUsageFirst" ::: |
| 66 | + |
| 67 | +In this example, the `NewAttribute` class can be applied to any supported program element. But it can be applied only once to each entity. The attribute is inherited by derived classes when applied to a base class. |
| 68 | + |
| 69 | +The <xref:System.AttributeUsageAttribute.AllowMultiple> and <xref:System.AttributeUsageAttribute.Inherited> arguments are optional, so the following code has the same effect: |
| 70 | + |
| 71 | +:::code language="csharp" source="snippets/NewAttribute.cs" id="SnippetUsageSecond" ::: |
| 72 | + |
| 73 | +The first <xref:System.AttributeUsageAttribute> argument must be one or more elements of the <xref:System.AttributeTargets> enumeration. Multiple target types can be linked together with the OR operator, like the following example shows: |
| 74 | + |
| 75 | +:::code language="csharp" source="snippets/NewPropertyOrFieldAttribute.cs" id="SnippetDefinePropertyAttribute" ::: |
| 76 | + |
| 77 | +Beginning in C# 7.3, attributes can be applied to either the property or the backing field for an auto-implemented property. The attribute applies to the property, unless you specify the `field` specifier on the attribute. Both are shown in the following example: |
| 78 | + |
| 79 | +:::code language="csharp" source="snippets/NewPropertyOrFieldAttribute.cs" id="SnippetUsePropertyAttribute" ::: |
| 80 | + |
| 81 | +If the <xref:System.AttributeUsageAttribute.AllowMultiple> argument is `true`, then the resulting attribute can be applied more than once to a single entity, as shown in the following example: |
| 82 | + |
| 83 | +:::code language="csharp" source="snippets/MultiUseAttribute.cs" id="SnippetMultiUse" ::: |
| 84 | + |
| 85 | +In this case, `MultiUseAttribute` can be applied repeatedly because `AllowMultiple` is set to `true`. Both formats shown for applying multiple attributes are valid. |
| 86 | + |
| 87 | +If <xref:System.AttributeUsageAttribute.Inherited> is `false`, then the attribute isn't inherited by classes derived from an attributed class. For example: |
| 88 | + |
| 89 | +:::code language="csharp" source="snippets/NonInheritedAttribute.cs" id="SnippetNonInherited" ::: |
| 90 | + |
| 91 | +In this case `NonInheritedAttribute` isn't applied to `DClass` via inheritance. |
| 92 | + |
| 93 | +## See also |
| 94 | + |
| 95 | +- <xref:System.Attribute> |
| 96 | +- <xref:System.Reflection> |
| 97 | +- [Attributes](../../../standard/attributes/index.md) |
| 98 | +- [Reflection](../../programming-guide/concepts/reflection.md) |
0 commit comments