概念
特性是一种容许咱们向程序的程序集添加元数据的语言结构,它是用于保存程序结构信息的某种特殊类型的类。
能够经过使用特性向程序添加声明性信息。一个声明性标签是经过放置在它所应用的元素前面的方括号([ ])来描述的。
MSDN解释为:特性提供功能强大的方法,用以将元数据或声明信息与代码(程序集、类型、方法、属性等)相关联。特性与程序实体关联后,便可在运行时使用名为“反射”的技术查询特性。
特性(Attribute)用于添加元数据,如编译器指令和注释、描述、方法、类等其余信息。.Net 框架提供了两种类型的特性:预约义特性和自定义特性。
特性具备如下属性:html
- 特性可向程序中添加元数据。元数据是有关在程序中定义的类型的信息。全部的 .NET 程序集都包含指定的一组元数据,这些元数据描述在程序集中定义的类型和类型成员。能够添加自定义特性,以指定所需的任何附加信息。
- 能够将一个或多个特性应用到整个程序集、模块或较小的程序元素(如类和属性)。
- 特性能够与方法和属性相同的方式接受参数。
- 程序能够使用反射检查本身的元数据或其余程序内的元数据。
使用特性
特性的目的是告诉编译器把程序结构的某组元数据嵌入程序集,它能够放置在几乎全部的声明中(但特定的属性可能限制在其上有效的声明类型)。
在 C# 中,特性的指定方法为:将括在方括号中的特性名置于其应用到的实体的声明上方。
例如:框架
[System.Serializable] public class SampleClass { // 运行语句 }
一个声明中能够放置多个特性,有两种写法。第一种是将独立的特性片断互相叠在一块儿,第二种是使用一个特性片断,特性之间使用逗号分割。ide
[System.Serializable] [MyAttribute("par1","par2")] // 独立的特性片断 public class SampleClass { // 运行语句 } [MyAttribute("par1","par2"), System.Serializable] // 逗号分割使用 public class SampleClass { // 运行语句 }
对于某些特性能够对给定实体进行指定屡次。例如 ConditionalAttribute :函数
[Conditional("DEBUG"), Conditional("TEST1")] void TraceMethod() { // 运行语句 }
特性目标
特性的目标是应用该特性的实体。例如,特性能够应用于类、特定方法或整个程序集。默认状况下,特性应用于它后面的元素。可是,您也能够显式标识要将特性应用于方法仍是它的参数或返回值。
语法:post
[target : attribute-list]
预约义特性
.Net 框架提供了三种预约义特性:AttributeUsage、Conditional、Obsolete。this
AttributeUsage
AttributeUsage 描述了如何使用一个自定义特性类。它规定了特性可应用到的项目的类型。
语法:spa
[AttributeUsage( validon, AllowMultiple=allowmultiple, Inherited=inherited )]
参数说明:debug
- validon: 规定特性可被放置的语言元素。它是枚举器 AttributeTargets 的值的组合。默认值是 AttributeTargets.All。
- allowmultiple:可选的参数,为该特性的 AllowMultiple 属性(property)提供一个布尔值。若是为 true,则该特性是多用的。默认值是 false(单用的)。
- inherited:可选的参数,为该特性的 Inherited 属性(property)提供一个布尔值。若是为 true,则该特性可被派生类继承。默认值是 false(不被继承)。
示例:3d
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = true)]
这个预约义特性标记了一个条件方法,其执行依赖于它顶的预处理标识符。
它会引发方法调用的条件编译,取决于指定的值,好比 Debug 或 Trace。例如,当调试代码时显示变量的值。
语法:调试
[Conditional( conditionalSymbol )]
示例:
using System; using System.Diagnostics; namespace C_Pro { public class Myclass { [Conditional("DEBUG")] public static void Msg(string msg) { Console.WriteLine(msg); } } public class Test { static void Main() { Myclass.Msg("debug in Main."); Console.WriteLine("Done."); Console.ReadKey(); } } }
以debug模式进行运行:
debug in Main. Done.
Obsolete
这个预约义特性标记了不该被使用的程序实体。它可让您通知编译器丢弃某个特定的目标元素。
语法:
[Obsolete( message, iserror )]
参数说明:
- message:是一个字符串,描述项目为何过期的缘由以及该替代使用什么。
- iserror:是一个布尔值。若是该值为 true,编译器应把该项目的使用看成一个错误。默认值是 false(编译器生成一个警告)。
示例:
using System; namespace C_Pro { public class MyClass { [Obsolete("Don't use OldMethod, use NewMethod instead", true)] static void OldMethod() { Console.WriteLine("It is the old method"); } [Obsolete("Don't use OldMethod, use NewMethod instead", false)] static void NewMethod() { Console.WriteLine("It is the new method"); } public static void Main() { OldMethod(); NewMethod(); Console.ReadKey(); } } }
运行后结果:
Main.cs(20,4): error CS0619: `C_Pro.MyClass.OldMethod()' is obsolete: `Don't use OldMethod, use NewMethod instead' Main.cs(21,4): warning CS0618: `C_Pro.MyClass.NewMethod()' is obsolete: `Don't use OldMethod, use NewMethod instead' Compilation failed: 1 error(s), 1 warnings
若是在 VS 中能够直接看到 OldMethod() 会报错提示:
自定义特性
声明特性和声明其余类是同样的,只是全部的特性都派生自System.Attribute。
根据约定,全部特性名称都以单词“Attribute”结束,以便将它们与“.NET Framework”中的其余项区分。可是,在代码中使用特性时,不须要指定 attribute 后缀。
例如定义一个MyAttributeAttribute,由 System.Attribute 派生而来,所以是自定义特性类。
public class MyAttributeAttribute : System.Attribute { public string product; public string Description; public MyAttributeAttribute(string product) { this.product = product; Description = ""; } }
特性也有构造函数。和其余类同样,每一个特性至少有一个公共构造函数,若是没有声明构造函数,编译器则会产生一个隐式、公共且无参的构造函数。
构造函数的参数是自定义特性的定位参数。例如上面的示例中 product 是定位参数,Description 是命名参数。任何公共的读写字段或属性都是命名参数。
定义完成后使用特性:
[Author("P. Pro", Description = "Description")] class SampleClass { // 执行语句 }
特性与注释的区别
注释是对程序源代码的一种说明,主要目的是给人看的,在程序被编译的时候会被编译器所丢弃,所以,它丝绝不会影响到程序的执行。
Attribute是程序代码的一部分,它不但不会被编译器丢弃,并且还会被编译器编译进程序集(Assembly)的元数据(Metadata)里。在程序运行的时候,随时能够从元数据(元数据:.NET中元数据是指程序集中的命名空间、类、方法、属性等信息,这些信息是能够经过Reflection读取出来的。)中提取提取出这些附加信息,并以之决策程序的运行。