.netframerwork中的索引器
我们可以使用数组来处理一组相同的类型,我们可以根据索引来获取每一个元素。那么既然是这样,我们为什么还要使用索引器呢?我们觉得有以下几点。
1,如果我们的类的意图本身就是想表示现实中的一组事物。本身就是一个群集的概念,那么我们就可以封装数组或集合成为索引器,让我们的类看上去像一个整体概念。这样有助与我们理解类的意图。使我们的类专注于表现群集的概念。这会使我们的类有数组的表现形式。更加形象化。还使其他开发人员能够更加直观地理解类及其用途。
2,使用数组有时候要依托于类里的数组。而索引器却是积极的表现类的意图,可以直接使用类索引
3,我们可以很轻易的使用别的类型来索引我们自己的类,当然数组也可以,但是相对比较麻烦,而且索引器更加直观的可以反映。
4,索引器是可以重载的,以至于我们可以使用多种类型进行索引
5,我们可以实现我们特定的索引逻辑
其实,索引器就是用我们的类来包装数组和集合,使我们的类看上去就是某个概念的集合,数组是把一组对象组合在一个容器中,而索引器则是把一组对象组合到我们的对象中。还是那句话,使其他开发人员能够更加直观地理解类及其用途。
下面我们就来看看一个最简单的索引器
首先定义我们的索引器类
public class Books<T> { public T[] arr = new T[1000]; public T this[int i] { get { return arr[i]; } set { arr[i] = value; } } }
这就是一个索引器,使用了this关键字,访问修饰符我们需要注意一下,这里使用了泛型。使用泛型的原因是给用户预留类型接口,当然你也可以不使用泛型,用object代替。但是装箱和拆箱的性能消耗是非常大的。其实这里我们看到了,索引器其实就是在类的内部封装数组或集合。这里的索引器类似一个属性,但是跟属性还是有区别。下面看看调用的代码
Books<string> books = new Books<string>(); books[0] = "Begin C#"; Console.WriteLine(books[0]);
这时候我们的类看起来就像一个集合了,使用的时候跟数组集合没什么区别。下面我们来重载一个索引器和用不同的类型索引。
public class Books<T> { private T[] arr = new T[1000]; public T this[int i] { get { return arr[i]; } set { arr[i]=value;} } public T this[string bookIndex] { get { try { int i = Convert.ToInt32(bookIndex); return arr[i]; } catch { throw new Exception("请提供正确的索引"); } } set { try { int i = Convert.ToInt32(bookIndex); arr[i]=value; } catch { throw new Exception("请提供正确的索引"); } } } }
这里我们既重载了索引,又使用了不同类型的参数来索引。我们还可以加上自己的逻辑,或者自己的类型来索引。
在接口中声明索引的方式跟在接口中声明方法的方式差不多,需要注意两点
1,索引没有访问修饰符
2,索引没有具体的实现
public interface IIdexer<T> { T this[int i] { get; set; } }
实现接口
public class Books<T>:IIdexer<T> { private T[] arr = new T[1000]; public T this[int i] { get { return arr[i]; } set { arr[i] = value; } } }
最后调用的方式是一样的。
下面总结一下使用索引器需要注意的
1,this关键字定义索引器
2,索引器可以有多个形参
3,索引器是访问修饰符必须让调用者有权限访问
4,重载索引器的时候,索引的签名由参数的类型和数量组成
5,索引不属于变量,不能作为ref和out参数进行传递
6,在接口里声明索引器,不能有访问修饰符,不能有实现,但是不能省略get和set
索引器与属性的区别
最后就是索引和属性的区别了。我就直接上图吧,直接切的MSDN上面的。