English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
特性(Attribute)是用于在运行时传递程序中各种元素(比如类、方法、结构、枚举、组件等)的行为信息的声明性标签。您可以通过使用特性向程序添加声明性信息。一个声明性标签是通过放置在它所应用的元素前面的方括号([ ])来描述的。
特性(Attribute)用于添加元数据,如编译器指令和注释、描述、方法、类等其他信息。.Net 框架提供了两种类型的特性:预定义特性和自定义特性。
指定特性(Attribute)的语法如下:
[attribute(positional_parameters, name_parameter = value, ...)] element
特性(Attribute)的名称和值是在方括号内指定的,放置在它所应用的元素之前。positional_parameters 指定必需的信息,name_parameter 指定可选的信息。
.Net 框架提供了三种预定义特性:
AttributeUsage
Conditional
Obsolete
预定义特性 AttributeUsage 描述了如何使用一个自定义特性类。它指定了特性可应用到的项目的类型。
La sintaxis para especificar esta característica es la siguiente:
[AttributeUsage( validon, AllowMultiple=allowmultiple, Inherited=inherited )]
donde:
参数 validon 指定特性可被放置的语言元素。它是枚举器 AttributeTargets 的值的组合。默认值是 AttributeTargets.All。
parámetro allowmultiple(opcional) La propiedad (property) inherited proporciona un valor booleano. Si es true, la característica es polimórfica. El valor predeterminado es false (monomórfica). 。 allowmultiple
parámetro AllowMultiple(opcional) La propiedad (property) inherited proporciona un valor booleano. Si es true, la característica es polimórfica. El valor predeterminado es false (monomórfica). Heredado El atributo (property) proporciona un valor booleano. Si es true, esta característica puede ser heredada por las subclases. El valor predeterminado es false (no se hereda).
Por ejemplo:
[AttributeUsage(AttributeTargets.Clase | AttributeTargets.Constructor | AttributeTargets.Campo | AttributeTargets.Método | AttributeTargets.Property, AllowMultiple = true)]
Esta característica predefinida marca un método condicional, cuya ejecución depende del identificador de preprocesamiento especificado.
causará la compilación condicional de llamadas a métodos, dependiendo del valor especificado, como depuración o rastreo. Por ejemplo, muestra el valor de las variables cuando se ejecuta el código de depuración.
La sintaxis para especificar esta característica es la siguiente:
[Conditional( simboloCondicional )]
Por ejemplo:
[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("En función 1.'); función2(); } static void function2()); { Myclass.Message("En función 2.'); } public static void Main() { Myclass.Message("En función principal."); función1(); Console.ReadKey(); } }
Cuando el código anterior se compila y ejecuta, produce los siguientes resultados:
En función principal En función 1 En función 2
Esta característica predefinida marca entidades de programa que no deben ser utilizadas. Le permite notificar al compilador que debe descartar un elemento de destino específico. Por ejemplo, cuando un nuevo método se utiliza en una clase, pero aún desea mantener el método antiguo en la clase, puede marcarlo como obsolete (obsoleto) mostrando un mensaje de que debe usar el nuevo método en lugar del antiguo.
La sintaxis para especificar esta característica es la siguiente:
[Obsoleto( message )] [Obsoleto( message, iserror )]
donde:
parámetro messagees una cadena que describe por qué el proyecto está obsoleto y qué usar en su lugar.
parámetro iserrores un valor booleano. Si este valor es true, el compilador debe tratar el uso de este proyecto como un error. El valor predeterminado es false (el compilador genera una advertencia).
下面的示例演示了该特性:
using System; public class MyClass { [Obsolete("No utilice OldMethod, utilice NewMethod en su lugar", true)] static void OldMethod() { Console.WriteLine("Es el método antiguo"); } static void NewMethod() { Console.WriteLine("Es el nuevo método"); } public static void Main() { OldMethod(); } }
当您尝试编译该程序时,编译器会给出一个错误消息说明:
No utilice OldMethod, utilice NewMethod en su lugar
.Net 框架允许创建自定义特性,用于存储声明性的信息,且可在运行时被检索。该信息根据设计标准和应用程序需要,可与任何目标元素相关。
创建并使用自定义特性包含四个步骤:
声明自定义特性
构建自定义特性
在目标程序元素上应用自定义特性
通过反射访问特性
最后一个步骤包含编写一个简单的程序来读取元数据以便查找各种符号。元数据是用于描述其他数据的数据和信息。该程序应使用反射来在运行时访问特性。我们将在下一章详细讨论这点。
一个新的自定义特性应派生自 System.Attribute 类。例如:
// Una característica personalizada BugFix se asigna a la clase y sus miembros [AttributeUsage(AttributeTargets.Clase | AttributeTargets.Constructor | AttributeTargets.Campo | AttributeTargets.Método | AttributeTargets.Property, AllowMultiple = true)] public class DeBugInfo : System.Attribute
在上面的代码中,我们已经声明了一个名为 DeBugInfo 的自定义特性。
让我们构建一个名为 DeBugInfo 的自定义特性,该特性将存储调试程序获得的信息。它存储下面的信息:
bug 的代码编号
辨认该 bug 的开发人员名字
最后一次审查该代码的日期
一个存储了开发人员标记的字符串消息
我们的 DeBugInfo 类将带有三个用于存储前三个信息的私有属性(property)和一个用于存储消息的公有属性(property)。所以 bug 编号、开发人员名字和审查日期将是 DeBugInfo 类的必需的定位(positional)参数,消息将是一个可选的命名(named)参数。
每个特性必须至少有一个构造函数。必需的定位(positional)参数应通过构造函数传递。下面的代码演示了 DeBugInfo Clase:}}
// Una característica personalizada BugFix se asigna a la clase y sus miembros [AttributeUsage(AttributeTargets.Clase | AttributeTargets.Constructor | AttributeTargets.Campo | AttributeTargets.Método | AttributeTargets.Property, AllowMultiple = true)] public class DeBugInfo : System.Attribute { privado int númeroError; privado string desarrollador; privado string últimaRevisión; public string message; public DeBugInfo(int bg, string dev, string d) { this.bugNo = bg; this.developer = dev; this.lastReview = d; } public int BugNo { obtener { regresar númeroError; } } public string Developer { obtener { regresar desarrollador; } } public string LastReview { obtener { regresar últimaRevisión; } } public string Message { obtener { regresar message; } establecer { message = valor; } } }
Aplicar la característica colocándola justo antes de su objetivo:
[DeBugInfo(45, "Zara Ali", "12/8/2012", Message = "Coincidencia de tipo de retorno no válida")] [DeBugInfo(49, "Nuha Ali", "10/10/2012", Message = "Variable no utilizada")] class Rectangle { // variable miembro protegido double longitud; protegido double ancho; public Rectangle(double l, double w) { longitud = l; ancho = w; } [DeBugInfo(55, "Zara Ali", "19/10/2012" Message = "Coincidencia de tipo de retorno no válida")] public double GetArea() { regresar longitud * width; } [DeBugInfo(56, "Zara Ali", "19/10/2012")] public void Display() { Console.WriteLine("Longitud: {0}", length); Console.WriteLine("Ancho: {0}", width); Console.WriteLine("Área: {0}", GetArea()); } }
En el siguiente capítulo, utilizaremos el objeto Reflection para recuperar esta información.