使用 C# 中的索引器和 JavaScript 中访问对象的属性是很相似。

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

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

索引器和属性的区别:

  1. 属性和索引器都是函数,但是表现形式不一样;(属性和索引器在代码的表现形式上和函数不一致,但其本质都是函数,需要通过 ILDASM 来查看,或者使用反射)
  2. 索引器可以被重载,而属性没有重载这一说法;(索引器的重载即方括号中的类型不同)
  3. 索引器不能声明为static,而属性可以;(索引器之所以不能声明为 static,因为其自身携带 this 关键字,需要被对象调用)

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

  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. //这里的代码时参照自http://www.cnblogs.com/ArmyShen/archive/2012/08/27/2659405.html的代码片段
  2. namespace Demo1
  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 >= 0 && index < 2)
  14. {
  15. return name[index];
  16. }
  17. return null;
  18. }
  19. //实现索引器的set方法
  20. set
  21. {
  22. if (index >= 0 && index < 2)
  23. {
  24. name[index] = value;
  25. }
  26. }
  27. }
  28. }
  29.  
  30. class Program
  31. {
  32. static void Main(string[] args)
  33. {
  34. //索引器的使用
  35. IndexerClass Indexer = new IndexerClass();
  36. //“=”号右边对索引器赋值,其实就是调用其set方法
  37. Indexer[0] = "张三";
  38. Indexer[1] = "李四";
  39. //输出索引器的值,其实就是调用其get方法
  40. Console.WriteLine(Indexer[0]);
  41. Console.WriteLine(Indexer[1]);
  42. }
  43. }
  44. }

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

上面再讲索引和属性的区别时,说到了索引其实也是函数,证明索引器是函数,我在上面的的代码中加入了一个普通方法 Add,

  1. public class IndexerClass
  2. {
  3. public string[] strArr = new string[2];
  4. //一个属性
  5. public int Age { get; set; }
  6. //一个方法
  7. public int Add(int a,int b)
  8. {
  9. return a + b;
  10. }
  11. //一个索引器
  12. public string this[int index]
  13. {
  14. get
  15. {
  16. if (index < 2 && index >= 0)
  17. return strArr[index];
  18. return null;
  19. }
  20. set
  21. {
  22. if (index >= 0 && index < 2)
  23. {
  24. strArr[index] = value;
  25. }
  26. }
  27. }
  28. }

我们将程序重新编译一下,然后使用 ILDASM 工具查看下编译出来的 .exe 文件,如下图:

从中我们可以看到一个 Add 的方法,这个小图标代表着方法,一共有 6 个方法,其中 .ctor 暂时不管,Add 方法是我们自己写的,

get_Age : int32(),这个方法是属性 age 的读方法,对应的还有个写方法;

还剩下两个就是索引器生成的方法了,get_Item:string(int32) 和 set_Item : void(int32) ;

还有这样的图标,这个图标是代表着字段,上面的两个字段是自动生成的,这也是 C#中的语法糖了,不用声明字段,只用声明属性,编译器会自动生成相应字段。

关于 C# 的语法糖可以点击这篇博客【 C# 中的语法糖

关于 ILDASM 的安装与使用可以点击这篇博客【ILDASM 的添加和使用

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

  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. //这里的代码时参照自http://www.cnblogs.com/ArmyShen/archive/2012/08/27/2659405.html的代码片段
  9. namespace Demo1
  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.  
  23. class Program
  24. {
  25. static void Main(string[] args)
  26. {
  27. IndexerClass Indexer = new IndexerClass();
  28. Indexer["A0001"] = "张三";
  29. Indexer["A0002"] = "李四";
  30. Console.WriteLine(Indexer["A0001"]);
  31. Console.WriteLine(Indexer["A0002"]);
  32. }
  33. }
  34. }

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

  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. //这里的代码时参照自http://www.cnblogs.com/ArmyShen/archive/2012/08/27/2659405.html的代码片段
  9. namespace Demo1
  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.  
  21. //2:通过Values存取key
  22. public int this[string aName]
  23. {
  24. get
  25. {
  26. //Hashtable中实际存放的是DictionaryEntry(字典)类型,如果要遍历一个Hashtable,就需要使用到DictionaryEntry
  27. foreach (DictionaryEntry d in name)
  28. {
  29. if (d.Value.ToString() == aName)
  30. {
  31. return Convert.ToInt32(d.Key);
  32. }
  33. }
  34. return -1;
  35. }
  36. set { name.Add(value, aName); }
  37. }
  38. }
  39.  
  40. class Program
  41. {
  42. static void Main(string[] args)
  43. {
  44. IndexerClass Indexer = new IndexerClass();
  45. //第一种索引器的使用
  46. Indexer[1] = "张三";//set访问器的使用
  47. Indexer[2] = "李四";
  48. Console.WriteLine("编号为1的名字:" + Indexer[1]);//get访问器的使用
  49. Console.WriteLine("编号为2的名字:" + Indexer[2]);
  50. Console.WriteLine();
  51. //第二种索引器的使用
  52. Console.WriteLine("张三的编号是:" + Indexer["张三"]);//get访问器的使用
  53. Console.WriteLine("李四的编号是:" + Indexer["李四"]);
  54. Indexer["王五"] = 3;//set访问器的使用
  55. Console.WriteLine("王五的编号是:" + Indexer["王五"]);
  56. }
  57. }
  58. }

具有多个参数的索引器:

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

C# 中常用的索引器的更多相关文章

  1. keras中常用的初始化器

    keras中常用的初始化器有恒值初始化器.正态分布初始化器.均匀分布初始化器 恒值初始化器: keras.initializers.Zeros() keras.initializers.Ones() ...

  2. C#中如何应用索引器 ( How to use Indexers )

    C#中索引器是个好东西, 可以允许类或者结构的实例像数组一样进行索引. 在foreach或者直接索引时很有用. 使用索引器可以简化客户端代码, 即调用者可以简化语法,直观理解类及其用途. 索引器只能根 ...

  3. 使用 Vue + TypeScript 时项目中常用的装饰器

    目录 一.@Component 装饰器 1)父组件 2)子组件 二. @Emit 装饰器 1)父组件 2)子组件 三. @Model 装饰器 1)父组件 2)子组件 四. @Prop 装饰器 1)父组 ...

  4. C# 索引器的理解和使用

    概述 此部分内容引用自MSDN文档 使用索引器可以用类似于数组的方式为对象建立索引. get 取值函数返回值. set 取值函数分配值. this 关键字用于定义索引器. value 关键字用于定义 ...

  5. C#中的索引器的简单理解和用法

    索引器是一种特殊的类成员,它能够让对象以类似数组的方式来存取,使程序看起来更为直观,更容易编写. 1.索引器的定义 C#中的类成员可以是任意类型,包括数组和集合.当一个类包含了数组和集合成员时,索引器 ...

  6. C#中索引器Indexer的学习使用

    索引器 顾名思义,是用来索引的,那么C#中索引器是用来索引什么的呢 首先我们知道,C#中的数组是本身就可以索引的,那么C#中的类和结构呢,类和结构的实例是无法索引的,如果我们想让C#中类或者结构的实例 ...

  7. C#类索引器的使用

    索引器提供了一种可以让类被当作数组进行访问的方式.在C#中,类索引器是通过this的属性实现的.index.ToString("D2")将index转换成一个具有两个字符宽度的字符 ...

  8. C# 索引器简介

    索引器是一种特殊的类成员,它能够让对象以类似数组的方式来存取,是程序看起来更为直观,更容易编写. 1.索引器的定义 C#中的类成员可以是任意类型,包括数组和集合.当一个类包含了数组和集合成员时,索引器 ...

  9. ylbtech-LanguageSamples-Indexers(索引器)

    ylbtech-Microsoft-CSharpSamples:ylbtech-LanguageSamples-Indexers(索引器) 1.A,示例(Sample) 返回顶部 “索引器”示例 本示 ...

随机推荐

  1. Asp.net core静态文件目录访问

    Asp.net core静态文件目录访问 如果使用Asp.net core来实现一个能够访问其它电脑上的资源 新建工程 选择项目框架 如何将静态文件注入到项目中 在startup.cs文件的Confi ...

  2. mysql自动提交

    MySQL的autocommit(自动提交)默认是开启,其对mysql的性能有一定影响,举个例子来说,如果你插入了1000条数据,mysql会commit1000次的,如果我们把autocommit关 ...

  3. MDK/Keil 中,J-Link调试查看变量值总是显示<not in scope>

    转载请注明出处,谢谢. MDK/Keil 中,J-Link调试查看变量值总是显示<not in scope> 原因:编译器把代码优化掉了,直接导致在仿真中变量根本没有分配内存,也就无法查看 ...

  4. 【blockly教程】第五章 循环结构

    在这里,我们将介绍一个新游戏--Pond Tutor 在Pond Tutor(https://blockly-games.appspot.com/pond-tutor)这个游戏中,我们将扮演黄色的鸭子 ...

  5. Caliburn.Micro 杰的入门教程3,事件和参数

    Caliburn.Micro 杰的入门教程1(翻译)Caliburn.Micro 杰的入门教程2 ,了解Data Binding 和 Events(翻译)Caliburn.Micro 杰的入门教程3, ...

  6. MySQL 取得字段子串修改

    MySQL 中, GeneID 为 GRMZM2G549533_P01,1123,45 , 需要修改为 GRMZM2G549533_P01 update test set GeneID=SUBSTRI ...

  7. eclipse导入jmeter3.1源码并运行

    jmeter3.1源码地址:https://archive.apache.org/dist/jmeter/source/ 1.打开eclipse,新建一个java project的项目,并点击next ...

  8. MaxScript代码补全插件

    MaxScript代码补全插件 作者Nik,原文发布于ScriptSpot 安装后max自带脚本编辑器会有自动补全,效果如下:

  9. js for循环实例

    1.求1-100的寄数和? //2.奇数求和 var ppt=0 for(var i=1;i<=100;i+=2){ ppt+=i } 2.求1-100的偶数和 var num=0 for(va ...

  10. Android开发-API指南-<permission>

    <permission> 英文原文:http://developer.android.com/guide/topics/manifest/permission-element.html 采 ...