本文實例分析了C#中Property和Attribute的區別。分享給大家供大家參考。具體分析如下:
在C#中有兩個屬性,分別為Property和Attribute,兩個的中文意思都有特性、屬性之間,但是用法上卻不一樣,為了區別,本文暫把Property稱為特性,把Attribute稱為屬性。
Attribute才是本文的主角,把它稱為屬性我覺得很恰當。屬性的意思就是附屬於某種事物上的,用來說明這個事物的各種特征的一種描述。而Attribute就是干這事的。它允許你將信息與你定義的C#類型相關聯,作為類型的標注。這些信息是任意的,就是說,它不是由語言本身決定的,你可以隨意建立和關聯任何類型的任何信息。你可以作用屬性定義設計時信息和運行時信息,甚至是運行時的行為特征。關鍵在於這些信息不僅可以被用戶取出來作為一種類型的標注,它更可以被編譯器所識別,作為編譯時的一種附屬條件參加程序的編譯。
以下部分內容及代碼來源於《C#技術揭秘》(Inside C# Sencond Edition)
定義屬性:
屬性實際上是一個派生自System.Attribute基類的類。System.Attribute類含有幾個用於訪問和檢查自定義屬性的方法。盡管你有權將任何類定義為屬性,但是按照慣例來說,從System.Attribute派生類是有意義的。示例如下:
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public enum RegHives { HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, HKEY_USERS, HKEY_CURRENT_CONFIG } public class RegKeyAttribute : Attribute { public RegKeyAttribute(RegHives Hive, String ValueName) { this.Hive = Hive; this.ValueName = ValueName; } protected RegHives hive; public RegHives Hive { get { return hive; } set { hive = value; } } protected String valueName; public String ValueName { get { return valueName; } set { valueName = value; } } }我們在這裡添加了不同注冊表的枚舉、屬性類的構造器以及兩個特性(Property)。在定義屬性時你可以做許許多多的事情,下面我們看看如何在運行時查詢屬性。要想在運行時查詢類型或成員所附著的屬性,必須使用反射
查詢類屬性:
假設你希望定義一個屬性,這個屬性定義了將在其上創建對象的遠程服務器。如果沒有這個屬性,就要把此信息保存在一個常量中或是一個應用程序的資源文件中。通過使用屬性,只需用以下方法標注出類的遠程服務器名即可:
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 using System; namespace QueryAttribs { public enum RemoteServers { JEANVALJEAN, JAVERT, COSETTE } public class RemoteObjectAttribute : Attribute { public RemoteObjectAttribute(RemoteServers Server) { this.server = Server; } protected RemoteServers server; public string Server { get { return RemoteServers.GetName( typeof(RemoteServers), this.server); } } } [RemoteObject(RemoteServers.COSETTE)] class MyRemotableClass { } class Test { [STAThread] static void Main(string[] args) { Type type = typeof(MyRemotableClass); foreach (Attribute attr in type.GetCustomAttributes(true)) { RemoteObjectAttribute remoteAttr = attr as RemoteObjectAttribute; if (null != remoteAttr) { Console.WriteLine( "Create this object on {0}.", remoteAttr.Server); } } Console.ReadLine(); } } }運行結果為:
Creat this object on COSETTE。
注意:在這個例子中的屬性類名具有Attribute後綴。但是,當我們將此屬性附著給類型或成員時卻不包括Attribute後綴。這是C#語言的設計者提供的簡單方式。當編譯器看到一個屬性被附著給一個類型或成員時,它會搜索具有指定屬性名的System.Attribute派生類。如果編譯器沒有找到匹配的類,它就在指定的屬性名後面加上Attribute,然後再進行搜索。因此,常見的使用做法是將屬性類名定義為以Attribute結尾,在使用時忽略名稱的這一部分。以下的代碼都采用這種命名方式。
查詢方法屬性:
在下面這個例子中,我們使用屬性將方法定義為可事務化的方法,只要存在TransactionableAttribute屬性,代碼就知道具有這個屬性的方法可以屬於一個事務。
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 using System; using System.Reflection; namespace MethodAttribs { public class TransactionableAttribute : Attribute { public TransactionableAttribute() { } } class SomeClass { [Transactionable] public void Foo() {} public void Bar() {} [Transactionable] public void Goo() {} } class Test { [STAThread] static void Main(string[] args) { Type type = Type.GetType("MethodAttribs.SomeClass"); foreach (MethodInfo method in type.GetMethods()) { foreach (Attribute attr in method.GetCustomAttributes(true)) { if (attr is TransactionableAttribute) { Console.WriteLine( "{0} is transactionable.", method.Name); } } } Console.ReadLine(); } }