讲索引器的本质前,先说说属性的本质,在IL里面我们可以清楚地看到,属性的get和set两个访问器,其实就是直接调用类里面定义的两个方法: set_属性名|get_属性名.
所以访问属性的途径,除了反射获取Propertie以外,我们可以绕过属性对象,直接调用set_属性名|get_属性名方法。
索引器除了具备属性的特性之外,索引器所对应的属性名必须为Item,如果一个类中定义了索引器,又定义了一个名为Item的属性,结果就会提示同名的错误.
除此之外,从IL中看出,属性本身就是特殊的方法,一般的属性都不带参数,而索引器至少带一个参数.如图:
1 public class getset 2 { 3 int[,] ary=new int[3,3] { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } }; 4 5 int _num; 6 public int Num 7 { 8 get 9 { 10 return _num; 11 } 12 set 13 { 14 _num=value; 15 } 16 } 17 public int this[int arg1] 18 { 19 get 20 { 21 return ary[arg1%3, arg1%3]; 22 } 23 set 24 { 25 ary[arg1%3, arg1%3]=value; 26 } 27 } 28 public int this[int arg1, int arg2] 29 { 30 get 31 { 32 return ary[arg1%3,arg2%3]; 33 } 34 set 35 { 36 ary[arg1%3, arg2%3]=value; 37 } 38 } 39 //索引器是特殊的属性 其属性名是Item 40 //定义Item属性无法通过编译 41 //public int Item 42 //{ 43 // get; 44 // set; 45 //} 46 public void Show() 47 { 48 for(int i=0;i<3;i++) 49 { 50 Console.WriteLine(ary[i, 0]+"\t"+ary[i, 1]+"\t"+ary[i, 2]); 51 } 52 } 53 54 public static void Test() 55 { 56 57 getset item=new getset(); 58 var type=typeof(getset); 59 var arg=new object[] { 2,2}; 60 61 foreach (var p in type.GetProperties().Where(o => o.Name=="Item")) 62 { 63 Console.Write("Parameter Length:"+p.GetIndexParameters().Length+"\r\n\t ReturenType:"+p.PropertyType+" Parameters Type:"); 64 foreach (var a in p.GetIndexParameters()) 65 { 66 Console.Write(a.ParameterType+"\t"); 67 } 68 Console.WriteLine(); 69 } 70 71 var method = type.GetMethod("get_Item",new Type[]{typeof(int),typeof(int)}); 72 Console.WriteLine(method.Invoke(item, arg)); 73 74 75 var prop = type.GetProperty("Item",typeof(int),new Type[]{typeof(int),typeof(int)}); 76 77 78 79 80 Console.WriteLine(prop.GetIndexParameters().Length); 81 82 prop.GetValue(item, arg); 83 84 prop.GetSetMethod().Invoke(item, new object[] { 123, 456,999}); 85 Console.WriteLine(prop.GetGetMethod().Invoke(item, new object[] { 2, 1 })); 86 87 88 item.Show(); 89 90 } 91 }