索引器的基础就不多说了,主要就是用对象加下标来获取对象内的私有序列数据。
下面看这样一个类:
class MyClass
{
string[] StrArr = new string[] { "a", "b", "c" };
public string this[int i]
{
get
{
return StrArr[i];
}
set
{
StrArr[i] = value;
}
}
可以看到,索引器本来是没有名字的,因为在这里是用一个this来代替。
做个反射,我们来看看索引器转成什么了。
static void Main(string[] args)
{
foreach (var v in typeof(MyClass).GetMembers())
{
Console.WriteLine(v.Name);
}
}
运行结果是:
get_Item
set_Item
ToString
Equals
GetHashCode
GetType
.ctor
Item
属性是由两个访问器方法构成,索引器同样也是,但有所不同的是,索引的这两个访问器方法增加了两个参数,并且方法名是固定的,如下:
{
}
{
}
这个固定的名称就是Item了,可以证名一下,可以在MyClass类中添加如下代码:
int item;
public int Item
{
get
{
return Item;
}
set
{
Item = value;
}
}
上面的代码加入后会报错,错误如下:
类型“ConsoleApplication7.MyClass”已经包含“Item”的定义。这就验证了索引器是一个Item了。
还有,索引器是可以重载的,在原来的MyClass中代码如下:
Hashtable ht = new Hashtable();
public MyClass()
{
ht.Add("1", "aaaaa");
ht.Add("2", "bbbbb");
ht.Add("3", "ccccc");
}
public object this[string i]
{
get
{
return ht[i];
}
set
{
ht[i] = value;
}
}
其实这个很好理解,也就是说这个实现了两个索引器get和set方法的重载。
如果一个索引器利用反射来调用,实现如下:
ConstructorInfo ci = typeof(MyClass).GetConstructor(new Type[0]);
MyClass mc = (MyClass)ci.Invoke(new Object[0]);
Console.WriteLine(typeof(MyClass).GetProperty("Item").GetValue(mc, new object[] { 1 }));
如果在一个类中,有两个索引器,这种情况就会报错,虽然在GetValue的第二个参数object[]中是整型的1,系统还是分不清,所以只能换用另一种方法了,如下:
ConstructorInfo ci = typeof(MyClass).GetConstructor(new Type[0]);
MyClass mc = (MyClass)ci.Invoke(new Object[0]);
Console.WriteLine(typeof(MyClass).GetProperties()[0].GetValue(mc, new object[] { 1 }));
Console.WriteLine(typeof(MyClass).GetProperties()[1].GetValue(mc, new object[] { "1" }));
本文转自桂素伟51CTO博客,原文链接: http://blog.51cto.com/axzxs/384906,如需转载请自行联系原作者