属性是用来传递信息到运行有关像类,方法,结构,枚举,集等各种元素的行为,在你的程序中声明的标签。可以通过使用属性添加声明信息的程序。声明性标记由正方形描绘([])置于它被用于元件上方括号。
属性用于添加元数据,如编译器的指令和其他信息,例如注释,描述,方法和类的程序。 .NET Framework提供了两种类型的属性:预先定义的属性和定制属性。
指定属性
指定属性的语法如下:
[attribute(positional_parameters, name_parameter = value, ...)]
element
属性的名称和值在方括号内指定的元素该属性的应用之前。位置参数指定的基本信息和名称参数指定的可选信息。
预定义的属性
.NET Framework提供了三个预定义的属性:
AttributeUsage
Conditional
Obsolete
AttributeUsage:
预先定义的属性AttributeUsage描述了如何自定义属性的类可以使用。它指定该属性可应用的项目类型。
用于指定该属性的语法如下:
[AttributeUsage(
validon,
AllowMultiple=allowmultiple,
Inherited=inherited
)]
这里,参数validon指明该属性可以放置在语言元素。它是一个枚举AttributeTargets的值的组合。默认值是AttributeTargets.All。
参数允许多个(可选)提供值这个属性,一个布尔值的AllowMultiple属性。如果是true,该属性为多用途。默认值为false(一次性使用)。
继承的参数(可选)提供值这个属性,一个布尔值的继承属性。如果是true,该属性由派生类继承。默认值是false(而不是继承)。
例如,
[AttributeUsage(AttributeTargets.Class |
AttributeTargets.Constructor |
AttributeTargets.Feild |
AttributeTargets.Method |
AttributeTargets.Property,
AllowMultiple = true)]
条件
此预定义属性标志着一个条件方法的执行依赖于一个指定的预处理标识符。
它引起的方法调用条件编译,根据所指定的值,如调试或跟踪。例如,它在调试代码显示变量的值。
用于指定该属性的语法如下:
[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(
message
)]
[Obsolete(
message,
iserror
)]
这里,该参数的消息,是一个描述原因的字符串显示为什么项目已经过时,用什么来代替。
该参数是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框架允许创建可用于存储信息的声明,并可以检索在运行时间自定义属性。这个信息可以与根据设计标准和应用的需要的任何目标元素。
创建和使用自定义属性包括四个步骤:
声明一个自定义属性
构造自定义属性
应用自定义属性的目标程序元素
通过反射访问属性
最后一步需要编写一个简单的程序来读取通过元数据来寻找各种符号。元数据是关于用于描述其他数据的数据或信息的数据。这个程序应该使用反射访问属性在运行时。为此,反射我们将在下一章中讨论。
声明自定义属性
一个新的自定义属性应该是从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类将有三个私有属性存储前三个信息,公共属性用于存储信息。所以这个bug数量,开发者的姓名和审查日期是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());
}
}