C#有參屬性(索引器)

來源:互聯網
上載者:User

無參屬性大家可以參考比對下。

今天又翻了翻書,看看有參屬性(索引器)跟無參屬性有啥區別。

屬性的get訪問器方法不接受參數,所以我們將這些屬性稱為無參屬性,因為無參屬性與欄位的訪問有些相似,所以這些屬性很容易理解。

除了這些與欄位訪問有些相似的屬性,C#還支援有參屬性(索引器),它的get訪問器方法接受一個或多個參數,set訪問器方法接受兩個或多個參數。

C#使用數組風格的文法來公開有參屬性,可以把索引器看作C#重載[]操作符的一種方式。

    class test
{
private int[] nums;
private int length;
public string sss
{
get;
set;
}
public test(int len)
{
if (len <= 0)
{
Console.WriteLine("輸入大於0的整數");
throw new ArgumentOutOfRangeException("輸入大於0的整數!");
}
length = len;
nums = new int[length];
}
//[IndexerName("Nums")]
public int this[int post]
{
get { if (post < 0 || post >= length) { Console.WriteLine("搞毛呢。。"); throw new ArgumentOutOfRangeException("post"); } else { return nums[post]; } }
set { if (post >= 0 && post < length&&nums!=null) { nums[post] = value; } else { throw new ArgumentOutOfRangeException("post", post.ToString()); } }
}
public string this[int i, string s]
{
get { return ""; }
set { }
}
}
class Program
{
static void Main()
{
PropertyInfo[] propertys = typeof(test).GetProperties();
foreach (PropertyInfo p in propertys)
{
Console.WriteLine("GetMethod的名稱:{0},SetMethod的名稱:{1}", p.GetGetMethod().Name, p.GetSetMethod().Name);
}
test t = new test(15);
for (int i = 0; i < 15; i++)
{
t[i] = i + 1;
Console.WriteLine(t[i]);
}
Console.ReadKey();
}

}

所有索引器至少要有一個參數,可以有更多,這些參數和傳回型別可以是除了void以外的任意類型。在System.Drawing.Imaging.ColorMatrix類中,提供了一個有多個參數的一個索引器的例子 ,大家可以去參考下 :

public float this[int row, int column]
{
get
{
return this.GetMatrix()[row][column];
}
set
{
float[][] numArray;
numArray = this.GetMatrix();
numArray[row][column] = value;
this.SetMatrix(numArray);
return;
}
}

經常要建立索引器來查詢關聯陣列中的值,System.Collections.Generic.Dictionary類就提供了這樣的一個索引器,它擷取一個值,並返回與該鍵關聯的值。

public TValue this[TKey key]
{
get
{
int num;
TValue local;
num = this.FindEntry(key);
if (num < 0)
{
goto Label_001E;
}
return &(this.entries[num]).value;
Label_001E:
ThrowHelper.ThrowKeyNotFoundException();
return default(TValue);
}
set
{
this.Insert(key, value, 0);
return;
}
}

和無參屬性不同,類型可以提供多個重載的索引器,只要這些索引器的簽名不同。

CLR本身並不區分無參屬性和有參屬性,對於CLR來說屬性就是類型中定義的一些方法和一些中繼資料。C#只允許在對象的執行個體上定義索引器,C#沒有提供定義靜態索引器屬性的文法,但是CLR是支援靜態有參屬性的。

由於C#的索引器文法不允許開放人員指定索引器名稱,所以編譯器就為索引器選擇了一個預設的名稱,如果你注意過你應該發現了吧:Item,編譯器產生的方法名就是get_Item,set_Item。從第一段代碼就能發現了

使用C#永遠不會看到Item這個名稱,所以一般不需要關心編譯器選定的這個名稱,但是如果為一個類型設計的索引器要是有其他語言的代碼訪問,就可能需要更改索引器的預設Item名稱了。C#允許向索引器應用System.Runtime.ComplierServices.IndexerNameAttribute定製attribute來重新命名這些方法。

       [IndexerName("Nums")]
public int this[int post]
{
get { if (post < 0 || post >= length) { Console.WriteLine("搞毛呢。。"); throw new ArgumentOutOfRangeException("post"); } else { return nums[post]; } }
set { if (post >= 0 && post < length&&nums!=null) { nums[post] = value; } else { throw new ArgumentOutOfRangeException("post", post.ToString()); } }
}
       public string this[int i, string s]//如果這裡不使用IndexerName修改預設的Item為Nums就會報錯:“兩個索引器的名稱不同;在類型中的每個索引器上的IndexerName特性都必須使用相同的名稱。”因為一個類型中可以定義多個索引器,只要索引器的參數集不同就行了,其他語言中IndexerName屬性允許定義多個具有相同簽名的索引器,每個索引器有不同的名稱,但是在C#中這是不允許的,因為它的文法不是通過名稱來引用索引器。
{
get { return ""; }
set { }
}


這裡編譯器就會產生名為get_Nums,set_Nums的方法,而不是預設的了。使用IndexerName 如果代碼中包含多個名稱不同的有參屬性,C#無法編譯代碼。
C#將索引器堪稱是對[]操作符的一種重載方式,而且[]操作符不能用來消除具有不同方法名和相同參數集的有參屬性的歧義。

關於有參屬性和無參屬性如果有沒指出來的地方,歡迎提出,大家共同進步…^_^

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.