1. 程式人生 > >CLR via C#學習筆記-第十章-有參屬性

CLR via C#學習筆記-第十章-有參屬性

get 類型參數 第十章 自動 spa ... ring 歧義 訪問性

10.2 有參屬性

屬性的get訪問器不接受參數,因此稱為無參屬性。

C#還支持有參屬性,他的get訪問器方法接受一個或多個參數,set訪問器方法接收兩個或多個參數,C#稱之為索引器。

C#使用數組風格的語法來公開有參屬性,換句話說可以將索引器看成是C#開發者對[]操作符的重載。

CLR中的有參屬性

索引器的set訪問器同樣包含了一個隱藏參數,在C#中稱為value。

CLR本身不區分無參屬性和有參屬性。對CLR來說每個屬性都只是類型定義中的定義的一對方法和一些元數據。

因為C#選擇了this[]作為表達索引器的語法,所以C#只允許在對象的實例上定義索引器。C#不支持定義靜態索引器屬性,雖然CLR是支持靜態有參屬性的。

CLR以相同方式對待有參無參屬性。編譯器在索引器名稱之前附加get_,set_前綴,從而自動生成這些訪問器方法的名稱。由於C#索引器不允許開發人員指定索引器名稱,C#編譯器不得不為訪問器方法選擇一個默認名稱,get_Item、set_Item。

修改索引器的訪問器方法的名字

如果為類型設計的索引器要由其他語言訪問,可能需要更改get、set訪問器方法所用的默認名稱Item。

[IndexerName("Bit")]
public Boolean this[Int32 bitPos]{...}

編譯時,C#編譯器會註意到IndexerName特性,會告訴編譯器如何對方法和屬性的元數據進行命名。

VB代碼演示如何訪問這個C#索引器

Dim ba as New BitArray(10)
vb用()而不是[]指定數組元素
Console.WriteLine(ba(2))
vb還允許通過索引器名稱來訪問他
Console.WriteLine(ba.Bit(2))

定義多個索引的註意事項

C#允許一個類型定義多個索引器,只要索引器的參數集不同。C#不允許定義多個相同簽名的索引器,因為C#編譯器不知道你用的那個索引器,它的語法不是通過名稱來引用索引器。

public Int32 this[Boolean b]{get{return 0;}}
[IndexerName("Jeff")]
public String this[Boolean b]{get{return null;}}

以上代碼會報錯,this具有相同參數類型的成員。

顯然C#將索引器看成是對[]操作符的重載,而[]操作符不能用來消除具有不同方法名和相同參數集的有參屬性的歧義。

BTW

String的索引器名稱是Chars不是Item。這個只讀屬性允許從字符串中獲得一個單獨的字符。

10.3 調用屬性訪問器方法時的性能

對於簡單的set、get方法,JIT編譯器會將代碼內聯。

這樣一來使用屬性而不使用字段就沒有性能上的損失。

內聯是指將方法的代碼,目前說的是訪問器的方法的代碼直接編譯到調用他的方法中。

這就避免了在運行時發出調用所產生的開銷,代價是編譯好的方法變得更大。

由於屬性訪問器方法包含的代碼一般很少,所以對內聯會生成的本機diamagnetic變得更小執行更快。

10.4 屬性訪問器的可訪問性

為get、set訪問器方法可以指定一種可訪問性。最常見的時提供公共get訪問器和受保護set訪問器。

public class SomeType
{
    private String m_name;
    public String Name
    {
        get{return m_name;}
        protected set{m_name=value;}
    }
}    

定義屬性時,如果兩個訪問器方法需要不同的可訪問性,C#要求必須為屬性本身指定限制最小的可訪問性。然後兩個訪問器只能選擇一個來使用限制較大的。

10.5 泛型屬性訪問器方法

屬性本質是方法,C#和CLR允許泛型方法,但是C#不允許定義屬性時引入他自己的泛型類型參數。

之所以不允許最主要的原因是概念上說不通。

屬性本應表示可供查詢或設置的某個對象特征。一旦引入泛型類型的參數就意味著有可能改變查詢設置行為。

但屬性不應該和行為沾邊。公開對象的行為無論是不是泛型都應該定義訪問而非屬性。

CLR via C#學習筆記-第十章-有參屬性