概念
特性是一種容許咱們向程序的程序集添加元數據的語言結構,它是用於保存程序結構信息的某種特殊類型的類。
能夠經過使用特性向程序添加聲明性信息。一個聲明性標籤是經過放置在它所應用的元素前面的方括號([ ])來描述的。
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讀取出來的。)中提取提取出這些附加信息,並以之決策程序的運行。