属性是一个声明性的标签,用于向运行时传递有关程序中各种元素(如类,方法,结构,枚举器,程序集等)的行为的信息。可以通过使用属性将声明性信息添加到程序。声明式标签由放置在其所用元素上方的方括号([]
)表示。
属性用于向程序添加元数据,如编译器指令和其他信息,如注释,描述,方法和类。.Net框架提供了两种类型的属性:预定义属性和自定义构建的属性。
指定属性
用于指定属性的语法如下:
[attribute(positional_parameters, name_parameter = value, ...)]
element
属性名称及其值在方括号内,在应用该属性的元素之前指定。位置参数指定必要信息,名称参数指定可选信息。
预定义属性
.Net
框架提供了三个预定义的属性:
- AttributeUsage
- Conditional
- Obsolete
预定义属性:AttributeUsage
预定义属性AttributeUsage
描述了如何使用自定义属性类。它指定可以应用该属性的项目的类型。
用于指定此属性的语法如下:
[AttributeUsage(
validon,
AllowMultiple=allowmultiple,
Inherited=inherited
)]
其中,
- 参数
validon
指定可以放置属性的语言元素。它是枚举器AttributeTargets
的值的组合。默认值为AttributeTargets.All
。 - 参数
allowmultiple
(可选)为此属性的AllowMultiple
属性提供了一个布尔值。 如果些值为:true
,则表示属性是多次使用。默认值为false
,表示一次性使用。 - 参数
inherited
(可选)为此属性的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
)]
其中,
- 参数 -
message
是一个字符串,描述项目过时的原因以及使用的替代方法。 - 参数 -
iserror
,是一个布尔值。 如果值为true
,则编译器应将该项目的使用视为错误。默认值为false
,编译器生成警告。
示例程序如下:
using System
public class MyClass
{
[Obsolete("Don&apost 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&apost 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
类有三个私有属性用于存储前三个信息和一个用于存储消息的公共属性。 因此,错误编号,开发人员名称和审查日期是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, "Maxsu", "12/8/2018", Message = "Return type mismatch")]
[DeBugInfo(49, "Sukyda", "10/10/2018", 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, "Maxsu", "19/10/2018", Message = "Return type mismatch")]
public double GetArea()
{
return length * width
}
[DeBugInfo(56, "Maxsu", "19/10/2018")]
public void Display()
{
Console.WriteLine("Length: {0}", length)
Console.WriteLine("Width: {0}", width)
Console.WriteLine("Area: {0}", GetArea())
}
}
在下一章中,使用Reflection
类对象检索属性信息。