查看: 321|回复: 0

[ASP.NET教程] C#中常用的索引器

发表于 2017-5-14 09:20:46

之前了解过索引器,当时还把索引器和属性给记混了, 以为索引器就是属性,下面写下索引器和属性的区别,以及怎么使用索引器

先说明一点,这里的索引器和数据库中的索引不一样,虽然都是找元素。

索引器和属性的区别:

  1. 属性是以名称来标识,而索引器是以函数的形式来标识(但是索引器不能完全理解为函数);
  2. 索引器可以被重载,而属性没有重载这一说法;
  3. 索引器不能声明为static,而属性可以;

还有一点就是索引很像数组,它允许一个对象可以像数组一样被中括号 [] 索引,但是和数组有区别,具体有:

  1. 数组的角标只能是数字,而索引器的角标可以是数字也可以是引用类型;
  2. 数组是一个变量,而索引器可以理解为一个函数;

我在代码中很少自己定义索引器,但是我却经常在用它,那是因为系统自定义了很多索引器,比如 ADO.NET 中对于 DataTable 和 DataRow 等类的各种遍历,查找,很多地方就是用的索引器,比如下面这篇博客中的代码就使用了很多系统自定义的索引器:

DataTable的AcceptChanges()方法和DataRow的RowState属性 (其中索引器的使用都以及注明,)

那我们如何自定索引器? 回到这篇博客第一句话,我曾经把索引器和属性弄混过,那就说明他俩很像,看下代码看是不是很像:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using System.Dynamic;
复制代码
  1. <font color="#ff0000">//这里的代码时参照自</font><font color="#ff0000">http://www.cnblogs.com/ArmyShen/archive/2012/08/27/2659405.html</font><font color="#ff0000">的代码片段</font>
  2. namespace ConsoleApplicationTest
  3. {
  4. public class IndexerClass
  5. {
  6. private string[] name = new string[2];
  7. //索引器必须以this关键字定义,其实这个this就是类实例化之后的对象
  8. public string this[int index]
  9. {
  10. //实现索引器的get方法
  11. get
  12. {
  13. if (index < 2)
  14. {
  15. return name[index];
  16. }
  17. return null;
  18. }
  19. //实现索引器的set方法
  20. set
  21. {
  22. if (index < 2)
  23. {
  24. name[index] = value;
  25. }
  26. }
  27. }
  28. }
  29. class Program
  30. {
  31. static void Main(string[] args)
  32. {
  33. //索引器的使用
  34. IndexerClass Indexer = new IndexerClass();
  35. //“=”号右边对索引器赋值,其实就是调用其set方法
  36. Indexer[0] = "张三";
  37. Indexer[1] = "李四";
  38. //输出索引器的值,其实就是调用其get方法
  39. Console.WriteLine(Indexer[0]);
  40. Console.WriteLine(Indexer[1]);
  41. }
  42. }
  43. }
复制代码

乍一眼看上去,感觉和属性一样了, 但是索引器多了的名称和属性的名称不一样,而且多了 this 关键字,看到这里的 this 的特殊用法又让我想到了扩展方法中的 this的特殊位置。

以字符串为角标, 这点就和数组不一样了:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using System.Dynamic;
  7. using System.Collections;
  8. <font color="#ff0000">//这里的代码时参照自</font><font color="#ff0000">http://www.cnblogs.com/ArmyShen/archive/2012/08/27/2659405.html</font><font color="#ff0000">的代码片段</font>
  9. namespace ConsoleApplicationTest
  10. {
  11. public class IndexerClass
  12. {
  13. //用string作为索引器下标的时候,要用Hashtable
  14. private Hashtable name = new Hashtable();
  15. //索引器必须以this关键字定义,其实这个this就是类实例化之后的对象
  16. public string this[string index]
  17. {
  18. get { return name[index].ToString(); }
  19. set { name.Add(index, value); }
  20. }
  21. }
  22. class Program
  23. {
  24. static void Main(string[] args)
  25. {
  26. IndexerClass Indexer = new IndexerClass();
  27. Indexer["A0001"] = "张三";
  28. Indexer["A0002"] = "李四";
  29. Console.WriteLine(Indexer["A0001"]);
  30. Console.WriteLine(Indexer["A0002"]);
  31. }
  32. }
  33. }
复制代码

索引器的重载,这点就是属性的不同:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using System.Dynamic;
  7. using System.Collections;
  8. <font color="#ff0000">//这里的代码时参照自</font><font color="#ff0000">http://www.cnblogs.com/ArmyShen/archive/2012/08/27/2659405.html</font><font color="#ff0000">的代码片段</font>
  9. namespace ConsoleApplicationTest
  10. {
  11. public class IndexerClass
  12. {
  13. private Hashtable name = new Hashtable();
  14. //1:通过key存取Values
  15. public string this[int index]
  16. {
  17. get { return name[index].ToString(); }
  18. set { name.Add(index, value); }
  19. }
  20. //2:通过Values存取key
  21. public int this[string aName]
  22. {
  23. get
  24. {
  25. //Hashtable中实际存放的是DictionaryEntry(字典)类型,如果要遍历一个Hashtable,就需要使用到DictionaryEntry
  26. foreach (DictionaryEntry d in name)
  27. {
  28. if (d.Value.ToString() == aName)
  29. {
  30. return Convert.ToInt32(d.Key);
  31. }
  32. }
  33. return -1;
  34. }
  35. set { name.Add(value, aName); }
  36. }
  37. }
  38. class Program
  39. {
  40. static void Main(string[] args)
  41. {
  42. IndexerClass Indexer = new IndexerClass();
  43. //第一种索引器的使用
  44. Indexer[1] = "张三";//set访问器的使用
  45. Indexer[2] = "李四";
  46. Console.WriteLine("编号为1的名字:" + Indexer[1]);//get访问器的使用
  47. Console.WriteLine("编号为2的名字:" + Indexer[2]);
  48. Console.WriteLine();
  49. //第二种索引器的使用
  50. Console.WriteLine("张三的编号是:" + Indexer["张三"]);//get访问器的使用
  51. Console.WriteLine("李四的编号是:" + Indexer["李四"]);
  52. Indexer["王五"] = 3;//set访问器的使用
  53. Console.WriteLine("王五的编号是:" + Indexer["王五"]);
  54. }
  55. }
  56. }
复制代码

具有多个参数的索引器:

  1. using System;
  2. using System.Collections;
  3. <font color="#ff0000">//这里的代码时参照自</font><font color="#ff0000">http://www.cnblogs.com/ArmyShen/archive/2012/08/27/2659405.html</font><font color="#ff0000">的代码片段</font>
  4. namespace ConsoleApplicationTest
  5. {
  6. /// <summary>
  7. /// 入职信息类
  8. /// </summary>
  9. public class EntrantInfo
  10. {
  11. //姓名、编号、部门
  12. public string Name { get; set; }
  13. public int Num { get; set; }
  14. public string Department { get; set; }
  15. }
  16. /// <summary>
  17. /// 声明一个类EntrantInfo的索引器
  18. /// </summary>
  19. public class IndexerForEntrantInfo
  20. {
  21. private ArrayList ArrLst;//用于存放EntrantInfo类
  22. public IndexerForEntrantInfo()
  23. {
  24. ArrLst = new ArrayList();
  25. }
  26. /// <summary>
  27. /// 声明一个索引器:以名字和编号查找存取部门信息
  28. /// </summary>
  29. /// <param name="name"></param>
  30. /// <param name="num"></param>
  31. /// <returns></returns>
  32. public string this[string name, int num]
  33. {
  34. get
  35. {
  36. foreach (EntrantInfo en in ArrLst)
  37. {
  38. if (en.Name == name && en.Num == num)
  39. {
  40. return en.Department;
  41. }
  42. }
  43. return null;
  44. }
  45. set
  46. {
  47. ArrLst.Add(new EntrantInfo()
  48. {
  49. Name = name,
  50. Num= num,
  51. Department = value
  52. });
  53. }
  54. }
  55. /// <summary>
  56. /// 声明一个索引器:以编号查找名字和部门
  57. /// </summary>
  58. /// <param name="num"></param>
  59. /// <returns></returns>
  60. public ArrayList this[int num]
  61. {
  62. get
  63. {
  64. ArrayList temp = new ArrayList();
  65. foreach (EntrantInfo en in ArrLst)
  66. {
  67. if (en.Num == num)
  68. {
  69. temp.Add(en);
  70. }
  71. }
  72. return temp;
  73. }
  74. }
  75. //还可以声明多个版本的索引器...
  76. }
  77. class Program
  78. {
  79. static void Main(string[] args)
  80. {
  81. IndexerForEntrantInfo Info = new IndexerForEntrantInfo();
  82. //this[string name, int num]的使用
  83. Info["张三", 101] = "人事部";
  84. Info["李四", 102] = "行政部";
  85. Console.WriteLine(Info["张三", 101]);
  86. Console.WriteLine(Info["李四", 102]);
  87. Console.WriteLine();
  88. //this[int num]的使用
  89. foreach (EntrantInfo en in Info[102])
  90. {
  91. Console.WriteLine(en.Name);
  92. Console.WriteLine(en.Department);
  93. }
  94. }
  95. }
  96. }
复制代码


回复

使用道具 举报