特性(Attribute)是用于在運(yùn)行時(shí)傳遞程序中各種元素(比如類、方法、結(jié)構(gòu)、枚舉、組件等)的行為信息的聲明性標(biāo)簽。您可以通過使用特性向程序添加聲明性信息。一個(gè)聲明性標(biāo)簽是通過放置在它所應(yīng)用的元素前面的方括號(hào)([ ])來描述的。
特性(Attribute)用于添加元數(shù)據(jù),如編譯器指令和注釋、描述、方法、類等其他信息。.Net 框架提供了兩種類型的特性:預(yù)定義特性和自定義特性。
列舉特性的語法如下:
[attribute(positional_parameters, name_parameter = value, ...)]
element
特性的名稱和值都是在方括號(hào)內(nèi)規(guī)定的,放在這個(gè)特性應(yīng)用的元素之前。表示位置的參數(shù)規(guī)定出特性的基本信息,名稱參數(shù)規(guī)定了可選擇的信息。
.Net Framework 提供了三種預(yù)定義的特性:
該特性描述了用戶定義的特性類是如何使用的。它規(guī)定了某個(gè)特性應(yīng)用的項(xiàng)目類型。
規(guī)定這種特性的語法如下:
[AttributeUsage(
validon,
AllowMultiple=allowmultiple,
Inherited=inherited
)]
其中,
例如:
[AttributeUsage(AttributeTargets.Class |
AttributeTargets.Constructor |
AttributeTargets.Field |
AttributeTargets.Method |
AttributeTargets.Property,
AllowMultiple = true)]
這個(gè)預(yù)定義特性標(biāo)記了一個(gè)條件方法,其執(zhí)行依賴于特定的預(yù)處理標(biāo)識(shí)符。
它會(huì)引起方法調(diào)用的條件編譯,取決于指定的值,比如 Debug 或 Trace。例如,當(dāng)調(diào)試代碼時(shí)顯示變量的值。
規(guī)定該特性的語法如下:
[Conditional(
conditionalSymbol
)]
例如:
[Conditional("DEBUG")]
下面的實(shí)例演示了該特性:
#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();
}
}
編譯執(zhí)行上述代碼,得到如下結(jié)果:
In Main function
In Function 1
In Function 2
這個(gè)預(yù)定義特性標(biāo)記了不應(yīng)被使用的程序?qū)嶓w。它可以讓您通知編譯器丟棄某個(gè)特定的目標(biāo)元素。例如,當(dāng)一個(gè)新方法被用在一個(gè)類中,但是您仍然想要保持類中的舊方法,您可以通過顯示一個(gè)應(yīng)該使用新方法,而不是舊方法的消息,來把它標(biāo)記為 obsolete(過時(shí)的)。
規(guī)定該特性的語法如下:
[Obsolete(
message
)]
[Obsolete(
message,
iserror
)]
其中,
下面的實(shí)例演示了該特性:
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();
}
}
當(dāng)你執(zhí)行這個(gè)程序時(shí),編譯器會(huì)提示如下的錯(cuò)誤:
Don't use OldMethod, use NewMethod instead
.Net 框架允許創(chuàng)建自定義特性,用于存儲(chǔ)聲明性的信息,且可在運(yùn)行時(shí)被檢索。該信息根據(jù)設(shè)計(jì)標(biāo)準(zhǔn)和應(yīng)用程序需要,可與任何目標(biāo)元素相關(guān)。
創(chuàng)建并使用自定義特性包含四個(gè)步驟:
最后一個(gè)步驟包含編寫一個(gè)簡單的程序來讀取元數(shù)據(jù)以便查找各種符號(hào)。元數(shù)據(jù)是用于描述其他數(shù)據(jù)的數(shù)據(jù)和信息。該程序應(yīng)使用反射來在運(yùn)行時(shí)訪問特性。我們將在下一章詳細(xì)討論這點(diǎn)。
一個(gè)新的自定義特性應(yīng)派生自 System.Attribute 類。例如:
//一個(gè)自定義的特性BugFix被分配給類和類的成員
[AttributeUsage(AttributeTargets.Class |
AttributeTargets.Constructor |
AttributeTargets.Field |
AttributeTargets.Method |
AttributeTargets.Property,
AllowMultiple = true)]
public class DeBugInfo : System.Attribute
在上面的代碼中,我們已經(jīng)聲明了一個(gè)名為 DeBugInfo 的自定義特性。
讓我們構(gòu)建一個(gè)名為 DeBugInfo 的自定義特性,該特性將存儲(chǔ)調(diào)試程序獲得的信息。它存儲(chǔ)下面的信息:
我們的 DeBugInfo 類將帶有三個(gè)用于存儲(chǔ)前三個(gè)信息的私有屬性(property)和一個(gè)用于存儲(chǔ)消息的公有屬性(property)。所以 bug 編號(hào)、開發(fā)人員名字和審查日期將是 DeBugInfo 類的必需的定位( positional)參數(shù),消息將是一個(gè)可選的命名(named)參數(shù)。
每個(gè)特性必須至少有一個(gè)構(gòu)造函數(shù)。必需的定位( positional)參數(shù)應(yīng)通過構(gòu)造函數(shù)傳遞。下面的代碼演示了 DeBugInfo 類:
//一個(gè)自定義的特性BugFix被分配給類和類的成員
[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;
}
}
}
通過將特性放置在目標(biāo)之前來使用它:
[DeBugInfo(45, "Zara Ali", "12/8/2012", Message = "Return type mismatch")]
[DeBugInfo(49, "Nuha Ali", "10/10/2012", Message = "Unused variable")]
class Rectangle
{
//成員變量
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());
}
}
在下一章節(jié)中,我們會(huì)介紹如何使用 Reflection 類來檢索特性信息。
更多建議: