首页 > 代码库 > c# 索引器

c# 索引器

1.索引器概述

c#中的索引器提供了语法的简洁方便的特性,它允许你访问对象元素如同访问数组那样,通常我们会在实现索引器的类的内部维护一个内部的集合或数组,通过索引器来实现对集合中的元素的存取操作。例如,我定义了一个row对象,内部维护了column数组,我们访问通过数组的方式访问row就相当于访问了对应的column元素,一目了然。代码如下:

   public class Row    {        private string[] _column;        public int Age { get; set; }        public Row(int len)        {            _column = new string[len];                    }        public string this[int index]        {            get { return _column[index]; }            set { _column[index] = value; }        }    }//测试代码:  class Program    {        static void Main(string[] args)        {            Row r = new Row(10);            for (int i = 0; i < 10; i++)            {                r[i] = i.ToString();            }            for (int i = 0; i < 10; i++)            {                Console.WriteLine("row["+i+"]="+r[i]);            }        }    }

程序运行的结果:

 

 

2.索引器的背后机制:

通过上面的代码的例子我们需要知道访问row[0]是究竟编译器帮我们在背后做了什么,同ildasm可以看到编译器为我们多生成了两个方法,一个是set_Item,一个是get_Item,如下图所示:

我们在看main方法生成的il中间码如下所示:

 1 .method private hidebysig static void  Main(string[] args) cil managed 2 { 3   .entrypoint 4   // Code size       117 (0x75) 5   .maxstack  4 6   .locals init ([0] class Test1.Row r, 7            [1] int32 i, 8            [2] bool CS$4$0000, 9            [3] object[] CS$0$0001)10   IL_0000:  nop11   IL_0001:  ldc.i4.s   1012   IL_0003:  newobj     instance void Test1.Row::.ctor(int32)13   IL_0008:  stloc.014   IL_0009:  ldc.i4.015   IL_000a:  stloc.116   IL_000b:  br.s       IL_002217   IL_000d:  nop18   IL_000e:  ldloc.019   IL_000f:  ldloc.120   IL_0010:  ldloca.s   i21   IL_0012:  call       instance string [mscorlib]System.Int32::ToString()22   IL_0017:  callvirt   instance void Test1.Row::set_Item(int32,23                                                          string)24   IL_001c:  nop25   IL_001d:  nop26   IL_001e:  ldloc.127   IL_001f:  ldc.i4.128   IL_0020:  add29   IL_0021:  stloc.130   IL_0022:  ldloc.131   IL_0023:  ldc.i4.s   1032   IL_0025:  clt33   IL_0027:  stloc.234   IL_0028:  ldloc.235   IL_0029:  brtrue.s   IL_000d36   IL_002b:  ldc.i4.037   IL_002c:  stloc.138   IL_002d:  br.s       IL_006b39   IL_002f:  nop40   IL_0030:  ldc.i4.441   IL_0031:  newarr     [mscorlib]System.Object42   IL_0036:  stloc.343   IL_0037:  ldloc.344   IL_0038:  ldc.i4.045   IL_0039:  ldstr      "row["46   IL_003e:  stelem.ref47   IL_003f:  ldloc.348   IL_0040:  ldc.i4.149   IL_0041:  ldloc.150   IL_0042:  box        [mscorlib]System.Int3251   IL_0047:  stelem.ref52   IL_0048:  ldloc.353   IL_0049:  ldc.i4.254   IL_004a:  ldstr      "]="55   IL_004f:  stelem.ref56   IL_0050:  ldloc.357   IL_0051:  ldc.i4.358   IL_0052:  ldloc.059   IL_0053:  ldloc.160   IL_0054:  callvirt   instance string Test1.Row::get_Item(int32)61   IL_0059:  stelem.ref62   IL_005a:  ldloc.363   IL_005b:  call       string [mscorlib]System.String::Concat(object[])64   IL_0060:  call       void [mscorlib]System.Console::WriteLine(string)65   IL_0065:  nop66   IL_0066:  nop67   IL_0067:  ldloc.168   IL_0068:  ldc.i4.169   IL_0069:  add70   IL_006a:  stloc.171   IL_006b:  ldloc.172   IL_006c:  ldc.i4.s   1073   IL_006e:  clt74   IL_0070:  stloc.275   IL_0071:  ldloc.276   IL_0072:  brtrue.s   IL_002f77   IL_0074:  ret78 } // end of method Program::Main

可以看到代码的22行和60行分别对应的是源码中的为row[i]赋值和取值的语句。我们不难猜测在set_Item和get_Item的代码内部是对Row内部的字符串数组_column进行操作。

从中我们可以总结出,索引器的背后原理实际是调用了对象的set方法和get方法,这就是索引器为我们带来的便利性,简化了我们变成的方式。

 

c# 索引器