標籤:oid 欄位 use false ++ 目錄 person 集合 field
目錄結構:
contents structure [+]
- 屬性和欄位的區別
- 無參屬性
- 自動實作屬性
- 對象和集合初始化器
- 匿名型別
- System.Tuple類型
- 有參屬性
- 屬性的可訪問性
在這篇文章中,將會詳細介紹屬性(Property)。屬性總的分為兩種,一種是有參屬性(索引器),另一種是無參屬性。
1.屬性和欄位的區別
屬性(Property)和欄位(Field)相比讀者都是見到過的,他們的區別見如下代碼:
class Person { public String m_name;//欄位 public Int32 m_age; public String Name{//屬性 get { return m_name; } set { m_name = value; }//關鍵字value代表新值 } public Int32 Age { get {return m_age;} set {m_age = value;} } }
從上面的定義的Person類可以看出,通常,封裝了欄位訪問的方法就是訪問器(屬性)。
2.無參屬性
無參屬性就是如同上面的Person類中的屬性,無索引器。
2.1 自動實作屬性
C#為無參屬性提供了一種更簡便的文法,稱為自動實現屬性(Automatically Implemented Property 簡稱為API)。
例如:
class Person { public String Name{set;get;} public Int32 Age{get;set;} }
上面C#會自動為Name和Age屬性聲明欄位,並且也會自動實現Name和Age屬性的主體方法,分別設定和返回欄位中的值。
2.2 對象和集合初始化器
經常要構造一個對象,並設定對象的一些公用屬性(或欄位),C#簡化了這個常見的編程模式。
還是以上面的Person類舉例,在有了Person類中,我們就可以聲明對象和初始化值一步完成(通過無參構造器):
Person person = new Person() { Name="jame",Age=12};
如果屬性實現了IEnumerable或是IEnumerable<T>介面,那麼屬性就會被認為是集合,例如:
class Classroom { public List<String> Student { set; get; } }
然後可以就使用如下的程式碼完成建立Classroom對象並且初始化Student屬性值。
Classroom classroom = new Classroom() { Student = { "green","red","blue"} };
2.3 匿名型別
C#可以利用匿名型別來聲明不可變(immutable)的元群組類型。一旦型別宣告完成後,就不可以更改。
例如:
var o1 = new {Name="jame",Age=12,Sex="男" };//o1.Name = "231";//編譯不通過,因為Name是唯讀屬性。Console.WriteLine(o1.Name);//jameConsole.WriteLine(o1.Age);//12Console.WriteLine(o1.Sex);//男
上面的代碼,C#自動建立一個匿名型別,並且含有Name、Age、Sex的唯讀屬性。
通過上面的代碼可以看出,C#提供匿名型別的文法是:
var o=new {perperty1=expression1,...,perpertyN=expressionN};
C#會推斷每個運算式的類型,並且建立類型的私人欄位,為每個欄位建立公用唯讀屬性,並且建立一個構造器來接受所有這些運算式。
2.4 System.Tuple類型
這裡介紹一下System.Tuple類型,因為System.Tuple類型中的所有屬性都是唯讀。System.Tuple有好幾個泛型版本,區別在於他們的元數(泛型參數的個數)。
//最簡單的泛型Tuple類型[Serializable]public class Tuple<T1>{ private readonly T1 m_Item1; public T1 Item1 { get { return m_Item1; } } public Tuple(T1 item1) { m_Item1 = item1; }}//最複雜的泛型Tuple泛型型別[Serializable]public class Tuple<T1, T2, T3, T4, T5, T6, T7, TRest>{ private readonly T1 m_Item1; private readonly T2 m_Item2; private readonly T3 m_Item3; private readonly T4 m_Item4; private readonly T5 m_Item5; private readonly T6 m_Item6; private readonly T7 m_Item7; private readonly TRest m_Rest; public T1 Item1 { get { return m_Item1; } } public T2 Item2 { get { return m_Item2; } } public T3 Item3 { get { return m_Item3; } } public T4 Item4 { get { return m_Item4; } } public T5 Item5 { get { return m_Item5; } } public T6 Item6 { get { return m_Item6; } } public T7 Item7 { get { return m_Item7; } } public TRest Rest { get { return m_Rest; } } public Tuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7, TRest rest) { m_Item1 = item1; m_Item2 = item2; m_Item3 = item3; m_Item4 = item4; m_Item5 = item5; m_Item6 = item6; m_Item7 = item7; m_Rest = rest; }}
Tuple類從System.Object派生,並且實現了IStructuralEquatable, IStructuralComparable介面,它們的是可比較的。
栗子:
static void Main(string[] args){ Tuple<Int32, Int32> vals = MinMax(12,21); Console.WriteLine(vals.Item1);//12 Console.WriteLine(vals.Item2);//21 Console.ReadLine();}static Tuple<Int32, Int32> MinMax(Int32 a, Int32 b) { return new Tuple<int, int>(Math.Min(a,b),Math.Max(a,b));}
3.有參屬性
我們將屬性的get訪問器是否能接受參數,分為無參屬性和有參數屬性(索引器)。
CLR本身是不區分有參屬性和無參屬性的。對CLR來說,每個屬性只是類型定義的一對方法和中繼資料。不同的程式設計語言使用使用了不同的文法來建立有參屬性,C#使用this[...]作為表達器索引的文法,因此C#只支援在對象的執行個體上定義索引器。
例如:
class BitArray { private Byte[] m_byteArray; private Int32 m_numBits; public BitArray(Int32 numBits) { //驗證實參 if (numBits <= 0) throw new ArgumentException("numBits must be > 0"); //儲存位的個數 m_numBits = numBits; //為位分配位元組 m_byteArray=new Byte[(numBits+7)/8];//之所以要加7,因為即使位元小於8,也應該有一個位元組。 } //下面是索引器(有參屬性) public Boolean this[Int32 bitPos] { get { if (bitPos < 0 || bitPos >= m_numBits) { throw new ArgumentException("bitPos"); } return (m_byteArray[bitPos/8]&(1<<(bitPos%8)))!=0;//判斷下標(bitPos%8)位的值是否不是0 } set { if (bitPos < 0 || bitPos >= m_numBits) { throw new ArgumentException("bitPos"); } if (value) { //將指定索引處的位設定為true m_byteArray[bitPos / 8] = (Byte)(m_byteArray[bitPos / 8] | (1 << (bitPos % 8)));//將下標(bitPos%8)位的值設定為1 } else { //將指定索引處的位設定為false m_byteArray[bitPos / 8] = (Byte)(m_byteArray[bitPos / 8] & ~(1 << (bitPos % 8)));//將下標(bitPos%8)的位的值設定0 } } }}
然後就可以像如下這樣來使用BitArray的索引器了。
BitArray ba = new BitArray(14);//調用set訪問器,將所有偶數位都設定為truefor (Int32 x = 0; x < 14; x++) { ba[x]=(x%2==0);}//調用get訪問器,顯示所有位的狀態。for (Int32 x = 0; x < 14; x++) { Console.WriteLine("Bit "+x+" is "+(ba[x]?"On":"Off"));}
4.屬性的可訪問性
有時希望為get訪問器方法提供一個可訪問性,為set訪問器方法指定另一種可訪問器。
例如:
public class SomeType{ private String m_name; public String Name{ get{return m_name;}//預設 protected set{m_name=value;}//指定為protected }}
【C#】詳解屬性