自1.0版本以來,c#對屬性進行了一系列的增強,讓其表達能力不斷提高。你可以對setter和geter指定不同的訪問權限。同時隱式屬性也極大降低了聲明屬性的工作量,不會比聲明數據成員麻煩多少。如果你還在類型中聲明公有成員,那麼快停下來吧,下面我們來對比一下兩者的優缺點:
1,屬性可以創建出類似於數據訪問,但實際上卻是方法調用的接口,所以它可以享受到方法調用的所有好處。
2,客戶代碼訪問屬性的時候,就像是在訪問公有字段,不過其底層使用方法實現,其中還可以自由定義屬性訪問器的行為。
3,.Net Framework中的數據綁定類僅支持屬性,而不支持公有數據成員,對所有的數據綁定類庫均是如此,包括WPF,Windows Forms和Silverlight。數據綁定機制將使用反射來找到類型中的特定屬性:
textBoxCity.DataBindings.Add("Text",address,"City");這段代碼將textBoxCity控件的Text屬性綁定到address對象的City屬性上。
4,在日後有新的需求或者行為時,屬性更易於修改。例如客戶要求名稱不能為空,若你使用了屬性來封裝Name,那麼只需要修改一處即可:
public class Customer { private string name; public string Name { get { return name; } set { if (string.IsNullOrEmpty(value)) { throw new ArgumentException("名稱不能為空","Name"); } name = value; } } }
但是如果使用了公有數據成員,你就需要查找每一處設置名稱的代碼並逐一修復。想想這會花費你多少時間。
5,由於屬性是使用方法來現實的,所以添加多線程支持也非常簡單,很容易在即有的屬性的get和set訪問器中做出如下修改:
public class Customer { private object syncHandle = new object(); private string name; public string Name { get { lock (syncHandle) return name; } set { if (string.IsNullOrEmpty(value)) { throw new ArgumentException("名稱不能為空", "Name"); } lock (syncHandle) name = value; } } }
6,屬性可以擁有方法的所有語言特性,例如屬性可以為虛的(virtual)
public virtual string Name { get; set; }
7,屬性的訪問器將作為兩個獨立的方法編譯到你的類型中。在c#中,你可以get和set訪問器設置不同的訪問權限。這樣你可以精妙的控制屬性暴露出來的數據成員的可見性:
public virtual string Name { get; protected set; }
8,屬性的功能很強大,是個不錯的改進。但是你是不是還在考慮先用公有數據成員來實現,然後再改成屬性呢?這個看似不錯的策略,其實卻行不通。來看下面的代碼:
public class Customer { public string Name; } string name=customerOne.Name; customerOne.Name="Jim";
看似簡單直觀,你可以認為若是日後將Name改成屬性,那麼代碼可以無需任何修改。但是這個答案並不是完全正確。屬性僅僅是在訪問時類似於數據成員,但是屬性的訪問和數據的訪問將會生成不同的MSIL語言。所以當你想更新單一程序集變得非常困難。
9,性能比較
若是你查看生成的IL,那麼你或許會比較一下兩者的性能,屬性當然不會比數據成員訪問快,不過也不會比它差多少,只要不在屬性訪問器中執行長時間的計算或者進行跨應用程序的調用(例如執行數據庫操作)。
無論何時需要在類型的公有或者保護接口中暴露數據,都應該使用屬性,所有的數據成員都應該是私有的,沒有任何例外。
對於將變量封裝成一個屬性所需的額外輸入工作其實不會占用太多時間,但是對於今後的維護卻帶來很大的方便。
如果成員變量公開,就會有程序安全隱患,所以我們一般就用屬性來封裝成員變量,屬性的本質就是方法,這樣就即安全方便又符合面向對象的概念。
B