属性(Attributes)
attribute是一个声明性标记,用于向运行时传递有关程序中各种元素(如类,方法,结构,枚举器,程序集等)的行为的信息。 您可以使用属性向程序添加声明性信息。 声明性标记由位于其所用元素上方的方括号([])括号表示。
属性用于向程序添加元数据,例如编译器指令和其他信息,例如注释,描述,方法和类。 .Net Framework提供两种类型的属性: the pre-defined属性和custom built属性。
指定属性
指定属性的语法如下 -
[attribute(positional_parameters, name_parameter = value, ...)]
element
属性的名称及其值在方括号内指定,在应用该属性的元素之前。 位置参数指定基本信息,名称参数指定可选信息。
预定义属性
.Net Framework提供三个预定义的属性 -
- AttributeUsage
- Conditional
- Obsolete
AttributeUsage (AttributeUsage)
预定义属性AttributeUsage描述了如何使用自定义属性类。 它指定可以应用属性的项目类型。
指定此属性的语法如下 -
[AttributeUsage (
validon,
AllowMultiple = allowmultiple,
Inherited = inherited
)]
Where,
参数validon指定可以放置属性的语言元素。 它是枚举器AttributeTargets的值的组合。 默认值为AttributeTargets.All 。
参数allowmultiple (可选)为此属性的AllowMultiple属性提供值,即布尔值。 如果是,则属性为多用途。 默认值为false(单次使用)。
继承的参数(可选)为此属性的Inherited属性提供值,即布尔值。 如果为true,则属性由派生类继承。 默认值为false(未继承)。
例如,
[AttributeUsage(
AttributeTargets.Class |
AttributeTargets.Constructor |
AttributeTargets.Field |
AttributeTargets.Method |
AttributeTargets.Property,
AllowMultiple = true)]
有条件的(Conditional)
此预定义属性标记条件方法,其执行取决于指定的预处理标识符。
它会导致方法调用的条件编译,具体取决于指定的值,如Debug或Trace 。 例如,它在调试代码时显示变量的值。
指定此属性的语法如下 -
[Conditional(
conditionalSymbol
)]
例如,
[Conditional("DEBUG")]
以下示例演示了该属性 -
#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();
}
}
编译并执行上述代码时,会产生以下结果 -
In Main function
In Function 1
In Function 2
过时 (Obsolete)
此预定义属性标记不应使用的程序实体。 它使您能够通知编译器丢弃特定的目标元素。 例如,当在类中使用新方法时,如果您仍希望在类中保留旧方法,则可以通过显示应使用新方法的消息而不是旧方法将其标记为过时。
指定此属性的语法如下 -
[Obsolete (
message
)]
[Obsolete (
message,
iserror
)]
Where,
参数message是一个字符串,用于描述项目过时的原因以及使用的内容。
参数iserror是一个布尔值。 如果其值为true,则编译器应将该项的使用视为错误。 默认值为false(编译器生成警告)。
以下程序演示了这一点 -
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();
}
}
当您尝试编译该程序时,编译器会显示一条错误消息,指出 -
Don't use OldMethod, use NewMethod instead
创建自定义属性
.Net Framework允许创建可用于存储声明性信息的自定义属性,并且可以在运行时检索。 根据设计标准和应用需求,此信息可与任何目标元素相关。
创建和使用自定义属性涉及四个步骤 -
- 声明自定义属性
- 构造自定义属性
- 在目标程序元素上应用自定义属性
- 通过反射访问属性
最后一步涉及编写一个简单的程序来读取元数据以查找各种符号。 元数据是关于用于描述其他数据的数据或信息的数据。 该程序应使用反射来在运行时访问属性。 我们将在下一章讨论。
声明自定义属性
应从System.Attribute类派生新的自定义属性。 例如,
//a custom attribute BugFix to be 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
在前面的代码中,我们声明了一个名为DeBugInfo的自定义属性。
构造自定义属性
让我们构造一个名为DeBugInfo的自定义属性,它存储通过调试任何程序获得的信息。 让它存储以下信息 -
- 错误的代号
- 识别错误的开发人员的姓名
- 上次审查代码的日期
- 用于存储开发人员备注的字符串消息
DeBugInfo类有三个用于存储前三个信息的私有属性和一个用于存储消息的公共属性。 因此,错误号,开发人员的姓名和审查日期是DeBugInfo类的位置参数,消息是可选的或命名参数。
每个属性必须至少有一个构造函数。 位置参数应该通过构造函数传递。 以下代码显示了DeBugInfo类 -
//a custom attribute BugFix to be 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;
}
}
}
应用自定义属性
通过将其放置在其目标之前来应用该属性 -
[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());
}
}
在下一章中,我们使用Reflection类对象检索属性信息。