c#編程基礎之二:特性 這裏的特性區別於屬性,雖然msdn中似乎並沒有區別二者。
屬性:是面向對象編程的基本概念,提供了對私有字段的訪問封裝,在C#中以get和set訪問器方法實現對可讀可寫屬性的操作,提供了安全和靈活的數據訪問封裝。
特性:公共語言運行時允許添加類似關鍵字的描述聲明,叫做attributes, 它對程序中的元素進行標註,如類型、字段、方法和屬性等。Attributes和Microsoft .NET Framework文件的元數據保存在一起,可以用來向運行時描述你的代碼,或者在程序運行的時候影響應用程序的行爲。比如 [Serializable]、[Flags]、[DllImport]、[AttributeUsage]
我們簡單的總結爲:定製特性attribute,本質上是一個類,其爲目標元素提供關聯附加信息,並在運行期以反射的方式來獲取附加信息。
我理解的定製特性,就是爲目標元素,可以是數據集、模塊、類、屬性、方法、甚至函數參數等加入附加信息,類似於註釋,但是可以在運行期以反射的方式獲得。定製特性主要應用在序列化、編譯器指令、設計模式等方面。
一、通用規則:
1、定製特性可以應用的目標元素可以爲:程序集(assembly)、模塊(module)、類型(type)、屬性(property)、事件(event)、字段(field)、方法(method)、參數(param)、返回值(return),應該全了。
2、定製特性以[,]形式展現,放在緊挨着的元素上,多個特性可以應用於同一元素,特性間以逗號隔開,以下表達規則有效:[AttributeUsage][ Flags]、[AttributeUsage, Flags]、[Flags, AttibuteUsageAttribute]、[AttributeUsage(), FlagesAttribute()]
3、attibute實例,是在編譯期進行初始化,而不是運行期。
4、C#允許以指定的前綴來表示特性所應用的目標元素,建議這樣來處理,因爲顯式處理可以消除可能帶來的二義性。例如:
using System;
namespace Anytao.net
{
[assembly: MyAttribute(1)] //應用於程序集
[moduel: MyAttribute(2)] //應用於模塊
pubic class Attribute_how2do
{
//
}
}
5、定製特性類型,必須直接或者間接的繼承自System.Attribute類,而且該類型必須有公有構造函數來創建其實例。
6、所有自定義的特性名稱都應該有個Attribute後綴,這是習慣性約定。
7、定製特性也可以應用在其他定製特性上,這點也很好理解,因爲定製特性本身也是一個類,遵守類的公有規則。例如很多時候我們的自定義定製特性會應用AttributeUsageAttribute特性,來控制如何應用新定義的特性。 [AttributeUsageAttribute(AttributeTarget.All),
AllowMultiple = true,
Inherited = true]
class MyNewAttribute: System.Attribute
{
//
}
8、定製特性不會影響應用元素的任何功能,只是約定了該元素具有的特質。
9、所有非抽象特性必須具有public訪問限制。
10、特性常用於編譯器指令,突破#define, #undefine, #if, #endif的限制,而且更加靈活。
11、定製特性常用於在運行期獲得代碼註釋信息,以附加信息來優化調試。
12、定製特性可以應用在某些設計模式中,如工廠模式。
13、定製特性還常用於位標記,非託管函數標記、方法廢棄標記等其他方面。
二、應用
1、常用特性
也就是.NET已經提供的固有特性,事實上在.NET框架中已經提供了豐富的固有特性由我們發揮。
AttributeUsage:用於控制如何應用自定義特性到目標元素。
Flags:以Flags特性來將枚舉數值看作位標記,而非單獨的數值,例如:
enum Animal
{
Dog = 0x0001,
Cat = 0x0002,
Duck = 0x0004,
Chicken = 0x0008
}
因此,以下實現就相當輕鬆,
Animal animals = Animal.Dog | Animal.Cat;
Console.WriteLine(animals.ToString());
請猜測結果是什麼,答案是:"Dog, Cat"。如果沒有Flags特性,這裏的結果將是"3"。
DllImport:DllImport特性,可以讓我們調用非託管代碼,所以我們可以使用DllImport特性引入對Win32 API函數的調用,對於習慣了非託管代碼的程序員來說,這一特性無疑是救命的稻草。
Serializable:表明了應用的元素可以被序列化
Conditional:用於條件編譯,在調試時使用。注意:Conditional不可應用於數據成員和屬性。
三、自定義特性
既然attribute,本質上就是一個類,那麼我們就可以自定義更特定的attribute來滿足個性化要求,只要遵守上述的12條規則,實現一個自定義特性其實是很容易的,典型的實現方法爲:
1、定義特性
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true)]
public class TestAttribute : System.Attribute
{
public TestAttribute(string message)
{
Console.WriteLine(message);
}
public void RunTest()
{
Console.WriteLine("TestAttribute here.");
}
}
2、應用目標元素
[Test("Error Here.")]
public void CannotRun()
{
//
}
3、獲取元素附加信息
如果沒有什麼機制來在運行期來獲取Attribute的附加信息,那麼attribute就沒有什麼存在的意義。因此,.NET中以反射機制來實現在運行期獲取attribute信息,實現方法如下:
public static void Main()
{
Tester t = new Tester();
t.CannotRun();
Type tp = typeof(Tester);
MethodInfo mInfo = tp.GetMethod("CannotRun");
TestAttribute myAtt = (TestAttribute)Attribute.GetCustomAttribute(mInfo, typeof(TestAttribute));
myAtt.RunTest();
}
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/changyuming/archive/2008/10/07/3027341.aspx