Attribute 一般譯作“特性”,Property 仍然譯為“屬性”。
1. Attribute 是什麼
Attribute 是一種可由使用者自由定義的修飾符(Modifier),可以用來修飾各種需要被修飾的目標。
簡單的說,Attribute就是一種“附著物” —— 就像牡蠣吸附在船底或礁石上一樣。
這些附著物的作用是為它們的附著體追加上一些額外的資訊(這些資訊就儲存在附著物的體內)—— 比如“這個類是我寫的”或者“這個函式以前出過問題”等等。
2. Attribute 的作用
特性Attribute 的作用是新增後設資料。
後設資料可以被工具支援,比如:編譯器用後設資料來輔助編譯,偵錯程式用後設資料來除錯程式。
3. Attribute 與註釋的區別
- 註釋是對程式原始碼的一種說明,主要目的是給人看的,在程式被編譯的時候會被編譯器所丟棄,因此,它絲毫不會影響到程式的執行。
- 而Attribute是程式程式碼的一部分,不但不會被編譯器丟棄,而且還會被編譯器編譯程式序集(Assembly)的後設資料(Metadata)裡,在程式執行的時候,你隨時可以從後設資料裡提取出這些附加資訊來決策程式的執行。
Attribute 的本質
莫非使用了Attribute 就相當於定義了新的修飾符(Modifier)嗎?讓我們來一窺究竟!示例程式碼如下:
#define XG //C# 的巨集定義必須出現在所有程式碼之前 using System; using System.Diagnostics; // 注意:這是為了使用包含在此名稱空間中的ConditionalAttribute 特性 namespace Con_Attribute { class Program2 { [Conditional("XG")] static void Fun() { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("http://xugang.cnblogs.com"); } static void Main(string[] args) { Fun(); } } }
使用微軟的中間語言反編譯器檢視 MSIL 中間語言中TargetMethod:void() 方法的程式碼,截圖如下:
可以看出:Attribute 本質上就是一個類,它在所附著的目標物件上最終例項化。
仔細觀察中間語言(MSIL)的程式碼之後,那些被C# 語言所掩蓋的事實,在中間語言(MSIL)中就變得赤身裸體了。而Attribute 也變得毫無祕密!
圖中紅色所指的是Fun 方法及其修飾符,但Attribute 並沒有出現在這裡。
圖中藍色所指的是在呼叫mscorlib.dll 程式集中System.Diagnostics 名稱空間中ConditionalAttribute 類的建構函式。
可見,Attribute 並不是修飾符,而是一個有著獨特例項化形式的類!
Attribute 例項化有什麼獨特之處呢?
1. 它的例項是使用.custom 宣告的。檢視中間語言語法,你會發現.custom 是專門用來宣告自定義特性的。
2. 宣告Attribute 的位置是在函式體內的真正程式碼(IL_0000 至IL_0014 )之前。
這就從“底層”證明了Attribute不是什麼“修飾符”,而是一種例項化方式比較特殊的類。
後設資料的作用
MSIL 中間語言中,程式集的後設資料(Metadata)記錄了這個程式集裡有多少個namespace、多少個類、類裡有什麼成員、成員的訪問級別是什麼。而且,後設資料是以文字(也就是Unicode 字元)形式存在的,使用.NET的反射(Reflection)技術就能把它們讀取出來,並形成MSIL 中的樹狀圖、VS 裡的Object Browser 檢視,以及自動程式碼提示功能,這些都是後設資料與反射技術結合的產物。一個程式集(.EXE或.DLL)能夠使用包含在自己體內的後設資料來完整地說明自己,而不必像C/C++ 那樣帶著一大捆標頭檔案,這就叫作“自包含性”或“自描述性”。