無參屬性大家可以參考比對下。
今天又翻了翻書,看看有參屬性(索引器)跟無參屬性有啥區別。
屬性的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 { }
}
www.2cto.com
這裡編譯器就會生成名為get_Nums,set_Nums的方法,而不是默認的了。使用IndexerName 如果代碼中包含多個名稱不同的有參屬性,C#無法編譯代碼。
C#將索引器堪稱是對[]操作符的一種重載方式,而且[]操作符不能用來消除具有不同方法名和相同參數集的有參屬性的歧義。
關於有參屬性和無參屬性如果有沒指出來的地方,歡迎提出,大家共同進步…^_^
作者 小小白白