YouTip LogoYouTip

Csharp Attribute

**Attributes** are declarative tags used at runtime to pass behavioral information about various elements in a program (such as classes, methods, structures, enums, components, etc.). You can use attributes to add declarative information to a program. A declarative tag is described by placing square brackets () in front of the element it applies to. Attributes are used to add metadata, such as compiler instructions, comments, descriptions, methods, classes, and other information. The .Net framework provides two types of attributes: _predefined_ attributes and _custom_ attributes. The syntax for specifying an attribute is as follows: [attribute(positional_parameters, name_parameter = value, ...)] element The name and value of the attribute are specified within the square brackets, placed before the element it applies to. positional_parameters specify required information, name_parameter specifies optional information. The .Net framework provides three predefined attributes: * AttributeUsage * Conditional * Obsolete ### AttributeUsage The predefined attribute **AttributeUsage** describes how to use a custom attribute class. It specifies the types of elements that the attribute can be applied to. The syntax for specifying this attribute is as follows: [AttributeUsage( validon, AllowMultiple=allowmultiple, Inherited=inherited )] Where: * The parameter _validon_ specifies the language elements that the attribute can be placed on. It is a combination of values from the _AttributeTargets_ enumerator. The default value is _AttributeTargets.All_. * The parameter _allowmultiple_ (optional) provides a boolean value for the attribute's _AllowMultiple_ property. If true, the attribute is multi-use. The default is false (single-use). * The parameter _inherited_ (optional) provides a boolean value for the attribute's _Inherited_ property. If true, the attribute can be inherited by derived classes. The default is false (not inherited). For example: [AttributeUsage(AttributeTargets.Class |AttributeTargets.Constructor |AttributeTargets.Field |AttributeTargets.Method |AttributeTargets.Property, AllowMultiple = true)] ### Conditional This predefined attribute marks a conditional method whose execution depends on a specified preprocessor identifier. It causes conditional compilation of a method call, depending on the specified value, such as **Debug** or **Trace**. For example, displaying the value of a variable when debugging code. The syntax for specifying this attribute is as follows: [Conditional( conditionalSymbol )] For example: [Conditional("DEBUG")] The following example demonstrates this attribute: ## Example #define DEBUG using System; using System.Diagnostics; public class Myclass { [Conditional("DEBUG")] public static void Message(string msg) { Console.WriteLine(msg); } } class Test { static void function1() { Myclass.Message("In Function 1."); function2(); } static void function2() { Myclass.Message("In Function 2."); } public static void Main() { Myclass.Message("In Main function."); function1(); Console.ReadKey(); } } When the above code is compiled and executed, it produces the following result: In Main function.In Function 1.In Function 2. ### Obsolete This predefined attribute marks a program entity that should not be used. It allows you to inform the compiler to discard a specific target element. For example, when a new method is used in a class, but you still want to keep the old method in the class, you can mark it as obsolete by displaying a message that the new method should be used instead of the old one. The syntax for specifying this attribute is as follows: [Obsolete( message )][Obsolete( message, iserror )] Where: * The parameter _message_ is a string describing why the item is obsolete and what to use instead. * The parameter _iserror_ is a boolean value. If true, the compiler should treat the usage of the item as an error. The default is false (the compiler generates a warning). The following example demonstrates this attribute: ## Example using System; public class MyClass { [Obsolete("Don't use OldMethod, use NewMethod instead", true)] static void OldMethod() { Console.WriteLine("It is the old method"); } static void NewMethod() { Console.WriteLine("It is the new method"); } public static void Main() { OldMethod(); } } When you try to compile the program, the compiler will give an error message stating: Don't use OldMethod, use NewMethod instead The .Net framework allows the creation of custom attributes to store declarative information that can be retrieved at runtime. This information can be associated with any target element based on design criteria and application needs. Creating and using custom attributes involves four steps: * Declaring a custom attribute * Building a custom attribute * Applying the custom attribute to target program elements * Accessing attributes through reflection The last step involves writing a simple program to read metadata to find various symbols. Metadata is data and information used to describe other data. The program should use reflection to access attributes at runtime. We will discuss this in detail in the next chapter. ### Declaring a Custom Attribute A new custom attribute should be derived from the **System.Attribute** class. For example: // A custom attribute BugFix is assigned to a class and its members[AttributeUsage(AttributeTargets.Class |AttributeTargets.Constructor |AttributeTargets.Field |AttributeTargets.Method |AttributeTargets.Property,AllowMultiple = true)]public class DeBugInfo : System.Attribute In the code above, we have declared a custom attribute named _DeBugInfo_. ### Building a Custom Attribute Let's build a custom attribute named _DeBugInfo_ that will store information obtained from debugging a program. It stores the following information: * The bug's code number * The name of the developer who identified the bug * The date of the last review of the code * A string message storing the developer's remarks Our _DeBugInfo_ class will have three private properties for storing the first three pieces of information and one public property for storing the message. Therefore, the bug number, developer name, and review date will be required positional parameters of the DeBugInfo class, and the message will be an optional named parameter. Each attribute must have at least one constructor. Required positional parameters should be passed through the constructor. The following code demonstrates the _DeBugInfo_ class: ## Example // A custom attribute BugFix is assigned to a class and its members [AttributeUsage(AttributeTargets.Class| AttributeTargets.Constructor| AttributeTargets.Field| AttributeTargets.Method| AttributeTargets.Property, AllowMultiple =true)] public class DeBugInfo :System.Attribute { private int bugNo; private string developer; private string lastReview; public string message; public DeBugInfo(int bg, string dev, string d) { this.bugNo= bg; this.developer= dev; this.lastReview= d; } public int BugNo { get { return bugNo; } } public string Developer { get { return developer; } } public string LastReview { get { return lastReview; } } public string Message { get { return message; } set { message =value; } } } ### Applying the Custom Attribute Apply the attribute by placing it immediately before its target: ## Example [DeBugInfo(45, "Zara Ali", "12/8/2012", Message ="Return type mismatch")] [DeBugInfo(49, "Nuha Ali", "10/10/2012", Message ="Unused variable")] class Rectangle { // Member variables protected double length; protected double width; public Rectangle(double l, double w) { length = l; width = w; } [DeBugInfo(55, "Zara Ali", "19/10/2012", Message ="Return type mismatch")] public double GetArea() { return length * width; } [DeBugInfo(56, "Zara Ali", "19/10/2012")] public void Display() { Console.WriteLine("Length: {0}", length); Console.WriteLine("Width: {0}", width); Console.WriteLine("Area: {0}", GetArea()); } } In the next chapter, we will use Reflection class objects to retrieve this information.
← Csharp ReflectionPr Text Unicode Bidi β†’