May 11, 2021 C#
Attributes are declaration labels that are used to deliver behavioral information about various elements in a program at runtime, such as classes, methods, structures, enumergies, components, and so on. Y ou can add declarative information to your program by using attributes. A declarative label is described by placing square brackets in front of the element it applies.
Attributes are used to add metadata, such as compiler instructions and comments, descriptions, methods, classes, and other information. The .Net framework provides two types of attributes: predefined attributes and custom attributes.
The syntax that specifies attributes is as follows:
[attribute(positional_parameters, name_parameter = value, ...)]
element
The name and value of the attribute are specified in square brackets and placed before the element it applies. positional_parameters information that is required, name_parameter information that is optional.
The .Net framework provides three predefined features:
The predefined attributeUsage describes how to use a custom attribute class. It specifies the types of items to which features can be applied.
The syntax that specifies this feature is as follows:
[AttributeUsage(
validon,
AllowMultiple=allowmultiple,
Inherited=inherited
)]
Among them:
For example:
[AttributeUsage(AttributeTargets.Class |
AttributeTargets.Constructor |
AttributeTargets.Field |
AttributeTargets.Method |
AttributeTargets.Property,
AllowMultiple = true)]
This predefined attribute marks a conditional method whose execution depends on its top preprocessed identifier.
It causes a conditional compilation of method calls, depending on the specified value, such as Debug or Trace. For example, the value of a variable is displayed when debugging code.
The syntax that specifies this feature is as follows:
[Conditional(
conditionalSymbol
)]
For example:
[Conditional("DEBUG")]
The following example demonstrates this feature:
#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 results:
In Main function
In Function 1
In Function 2
The conditional method is defined using Conditional in C#
With the Conditional property, programmers can define conditional methods. T he Conditional property compiles symbols by testing conditions to determine the applicable conditions. W hen you run to a conditional method call, whether the call is executed is determined by whether the symbol was defined when the call appeared. If this symbol is defined, the call is executed;
Using Conditional is an #if to #endif and internal approaches to the system, making it cleaner, more chic, and less likely to go wrong.
Conditional methods are subject to the following restrictions:
It's important to note here that if you create a method that doesn't define any conditions, the default call always executes this method, and if you want to judge execution by conditions, the method must contain at least one condition defined by the content attribute before it responds to the conditions that you define
This predefined attribute marks program entities that should not be used. I t lets you notify the compiler to drop a particular 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 (obsolete) by displaying a message that the new method should be used instead of the old method.
The syntax that specifies this feature is as follows:
[Obsolete(
message
)]
[Obsolete(
message,
iserror
)]
Among them:
The following example demonstrates this feature:
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 gives an error message description:
Don't use OldMethod, use NewMethod instead
The .Net framework allows you to create custom attributes that store declarative information and can be retrieved at runtime. This information can be relevant to any target element, depending on design criteria and application needs.
Creating and using custom features consists of four steps:
The final step consists of writing a simple program to read metadata to find symbols. M etadata is data and information used to describe other data. T he program should use reflection to access attributes at runtime. We'll discuss this in more detail in the next chapter.
A new custom feature should be derived from the System.Attribute class. For example:
// 一个自定义特性 BugFix 被赋给类及其成员
[AttributeUsage(AttributeTargets.Class |
AttributeTargets.Constructor |
AttributeTargets.Field |
AttributeTargets.Method |
AttributeTargets.Property,
AllowMultiple = true)]
public class DeBugInfo : System.Attribute
In the code above, we've declared a custom feature called DeBugInfo.
Let's build a custom feature called DeBugInfo that stores the information that the debugger gets. It stores the following information:
Our DeBugInfo class will have three private properties (property) for storing the first three messages and one public property (property) for storing messages. So the bug number, developer name, and review date will be the required positioning parameters for the DeBugInfo class, and the message will be an optional named parameter.
Each attribute must have at least one constructor. T he required positioning parameters should be passed through the constructor. The following code demonstrates the DeBugInfo class:
// 一个自定义特性 BugFix 被赋给类及其成员
[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;
}
}
}
Apply a feature by placing it immediately before its target:
[DeBugInfo(45, "Zara Ali", "12/8/2012", Message = "Return type mismatch")]
[DeBugInfo(49, "Nuha Ali", "10/10/2012", Message = "Unused variable")]
class Rectangle
{
// 成员变量
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'll use the Reflection class object to retrieve this information.