之前了解过索引器,当时还把索引器和属性给记混了, 以为索引器就是属性,下面写下索引器和属性的区别,以及怎么使用索引器
先说明一点,这里的索引器和数据库中的索引不一样,虽然都是找元素。
索引器和属性的区别:
还有一点就是索引很像数组,它允许一个对象可以像数组一样被中括号 [] 索引,但是和数组有区别,具体有:
- 数组的角标只能是数字,而索引器的角标可以是数字也可以是引用类型;
- 数组是一个变量,而索引器可以理解为一个函数;
我在代码中很少自己定义索引器,但是我却经常在用它,那是因为系统自定义了很多索引器,比如 ADO.NET 中对于 DataTable 和 DataRow 等类的各种遍历,查找,很多地方就是用的索引器,比如下面这篇博客中的代码就使用了很多系统自定义的索引器:
DataTable的AcceptChanges()方法和DataRow的RowState属性 (其中索引器的使用都以及注明,)
那我们如何自定索引器? 回到这篇博客第一句话,我曾经把索引器和属性弄混过,那就说明他俩很像,看下代码看是不是很像:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Dynamic;
//这里的代码时参照自http://www.cnblogs.com/ArmyShen/archive/2012/08/27/2659405.html的代码片段 namespace ConsoleApplicationTest { public class IndexerClass { private string[] name = new string[2]; //索引器必须以this关键字定义,其实这个this就是类实例化之后的对象 public string this[int index] { //实现索引器的get方法 get { if (index < 2) { return name[index]; } return null; } //实现索引器的set方法 set { if (index < 2) { name[index] = value; } } } } class Program { static void Main(string[] args) { //索引器的使用 IndexerClass Indexer = new IndexerClass(); //“=”号右边对索引器赋值,其实就是调用其set方法 Indexer[0] = "张三"; Indexer[1] = "李四"; //输出索引器的值,其实就是调用其get方法 Console.WriteLine(Indexer[0]); Console.WriteLine(Indexer[1]); } } }
乍一眼看上去,感觉和属性一样了, 但是索引器多了的名称和属性的名称不一样,而且多了 this 关键字,看到这里的 this 的特殊用法又让我想到了扩展方法中的 this的特殊位置。
以字符串为角标, 这点就和数组不一样了:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Dynamic; using System.Collections; //这里的代码时参照自http://www.cnblogs.com/ArmyShen/archive/2012/08/27/2659405.html的代码片段 namespace ConsoleApplicationTest { public class IndexerClass { //用string作为索引器下标的时候,要用Hashtable private Hashtable name = new Hashtable(); //索引器必须以this关键字定义,其实这个this就是类实例化之后的对象 public string this[string index] { get { return name[index].ToString(); } set { name.Add(index, value); } } } class Program { static void Main(string[] args) { IndexerClass Indexer = new IndexerClass(); Indexer["A0001"] = "张三"; Indexer["A0002"] = "李四"; Console.WriteLine(Indexer["A0001"]); Console.WriteLine(Indexer["A0002"]); } } }
索引器的重载,这点就是属性的不同:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Dynamic; using System.Collections; //这里的代码时参照自http://www.cnblogs.com/ArmyShen/archive/2012/08/27/2659405.html的代码片段 namespace ConsoleApplicationTest { public class IndexerClass { private Hashtable name = new Hashtable(); //1:通过key存取Values public string this[int index] { get { return name[index].ToString(); } set { name.Add(index, value); } } //2:通过Values存取key public int this[string aName] { get { //Hashtable中实际存放的是DictionaryEntry(字典)类型,如果要遍历一个Hashtable,就需要使用到DictionaryEntry foreach (DictionaryEntry d in name) { if (d.Value.ToString() == aName) { return Convert.ToInt32(d.Key); } } return -1; } set { name.Add(value, aName); } } } class Program { static void Main(string[] args) { IndexerClass Indexer = new IndexerClass(); //第一种索引器的使用 Indexer[1] = "张三";//set访问器的使用 Indexer[2] = "李四"; Console.WriteLine("编号为1的名字:" + Indexer[1]);//get访问器的使用 Console.WriteLine("编号为2的名字:" + Indexer[2]); Console.WriteLine(); //第二种索引器的使用 Console.WriteLine("张三的编号是:" + Indexer["张三"]);//get访问器的使用 Console.WriteLine("李四的编号是:" + Indexer["李四"]); Indexer["王五"] = 3;//set访问器的使用 Console.WriteLine("王五的编号是:" + Indexer["王五"]); } } }
具有多个参数的索引器:
using System; using System.Collections; //这里的代码时参照自http://www.cnblogs.com/ArmyShen/archive/2012/08/27/2659405.html的代码片段 namespace ConsoleApplicationTest { /// <summary> /// 入职信息类 /// </summary> public class EntrantInfo { //姓名、编号、部门 public string Name { get; set; } public int Num { get; set; } public string Department { get; set; } } /// <summary> /// 声明一个类EntrantInfo的索引器 /// </summary> public class IndexerForEntrantInfo { private ArrayList ArrLst;//用于存放EntrantInfo类 public IndexerForEntrantInfo() { ArrLst = new ArrayList(); } /// <summary> /// 声明一个索引器:以名字和编号查找存取部门信息 /// </summary> /// <param name="name"></param> /// <param name="num"></param> /// <returns></returns> public string this[string name, int num] { get { foreach (EntrantInfo en in ArrLst) { if (en.Name == name && en.Num == num) { return en.Department; } } return null; } set { ArrLst.Add(new EntrantInfo() { Name = name, Num= num, Department = value }); } } /// <summary> /// 声明一个索引器:以编号查找名字和部门 /// </summary> /// <param name="num"></param> /// <returns></returns> public ArrayList this[int num] { get { ArrayList temp = new ArrayList(); foreach (EntrantInfo en in ArrLst) { if (en.Num == num) { temp.Add(en); } } return temp; } } //还可以声明多个版本的索引器... } class Program { static void Main(string[] args) { IndexerForEntrantInfo Info = new IndexerForEntrantInfo(); //this[string name, int num]的使用 Info["张三", 101] = "人事部"; Info["李四", 102] = "行政部"; Console.WriteLine(Info["张三", 101]); Console.WriteLine(Info["李四", 102]); Console.WriteLine(); //this[int num]的使用 foreach (EntrantInfo en in Info[102]) { Console.WriteLine(en.Name); Console.WriteLine(en.Department); } } } }