1. C#的屬性在被訪問的時候看起來好像是數據成員,但其實是方法。
2. 在.NET框架中,一般使用屬性表達公有數據成員。
3. .NET框架中的數據綁定類支持屬性。
1. 隨著時間的推移,新的需求影響原來類型的實現。比如在員工管理系統中有如下代碼:
public class Person { private string name; public string Name { get{return name;} set{this.name = value;} } ....//其它屬性 } View CodePerson類聲明了一個Name的屬性,表示這個人的名字。程序運行了一段時間後,需求發生了變化,要求Name必須不為null或者empty。
我們一般的做法會是1)在界面輸入的地方增加驗證;2)寫一個單獨的程序或者sql修改數據庫的數據。但問題來了如果這個Person類有好幾個錄入的界面,比如員工的增加界面、員工修改界面,在修改的時候就要修改兩次。大家肯定發現了,如果有很多這樣界面,那麼就需要修改很多這樣的地方。再比如Person類被很多子類繼承了,比如Leader、BussinessMan等,那麼就需要在每個用到這些類地方進行修改。幸虧我們寫的是C#,幸虧你用的是屬性。只需要完成以下修改就可以到達我們的目的了。
public class Person { private string name; public string Name { get{return name;} set { if(string.IsNullOrEmpty(value)) { throw new ArgumentException("Name cannot be blank","Name"); } this.name = value; } } ....//其它屬性 } View Code
這樣是不是很方便?類似的,屬性添加多線程支持更方便、可以作為接口定義的一部分、可以聲明為虛屬性、訪問權限控制等。這些都是平常大家都會用的,此處就不再細說。
2. 索引器
如果類型接口需要包含一些索引數據項,那麼這個時候可以使用索引器。C#中索引器又叫含參屬性(parameterized property)。這個語法大家一般不會聲明,但卻都在使用。比如說
List<int> intList = new List<int>();
Console.Write(intList[0]);
大家可能經常寫這種代碼,但只是對這個語法的名字不太熟悉,或者經常寫但不知道如何聲明這種語法。其實這個就是索引器,聲明的語法也很簡單。比如一個人可能有多個地址(工作地址、家庭住址、籍貫地址等等),代碼如下:
public class Person { private Dictionary<string,Address> addrDic = new Dictionary<string,string>(); public Address this[string name] { get { return addrDic[name]; } set { this.addrDic[name] = value;//此處也可以改為先判斷有沒有key,沒有key就添加。 } } }
除此之外,C#還支持多維索引器,比如public object this[row,col],可以表示一個excel表格的某行某列的單元格裡面的值,這樣封裝後的Excel幫助類肯定比xx.GetExcelValue(row,col)這種方法更容易使用。
顯而易見,使用屬性的代碼沒有使用數據成員的代碼效率快(因為屬性本質上是方法)。但是,屬性也不見得比說那個數據成員的代碼慢。這是為什麼呢?JIT編譯器會對方法進行內聯處理(具體含義自行google),屬性作為方法的一種也是會進行內聯處理,那麼屬性和數據成員的效率就沒有區別。當然,即便沒有被內聯,屬性調用的效率相對於函數調用的成本也是可以忽略不計的,只有在一些極少數的情況下這種差別才值得我們注意。
這個問題,大家只記住不可以就行了。具體原因如下:
1. 對於屬性和公有字段使用的源代碼看起來一樣但IL代碼是不一樣的;
2. 如果一個類型的公有數據成員改為屬性,那麼會破壞二進制的兼容性,在程序已經部署的情況下可能會帶來升級的麻煩。
1. 對於暴漏在類型的公有接口或者受保護接口中的數據,我們應該使用屬性。
2. 對於具有序列或者字典特征的類型,我們應該采用索引器。
3. 對於所有的數據成員,我們應該都應該聲明為私有。