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]);
            }
        }


    }

程序运行的结果:

 

c# 索引器

 

2.索引器的背后机制:

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

c# 索引器

我们在看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:  nop
11   IL_0001:  ldc.i4.s   10
12   IL_0003:  newobj     instance void Test1.Row::.ctor(int32)
13   IL_0008:  stloc.0
14   IL_0009:  ldc.i4.0
15   IL_000a:  stloc.1
16   IL_000b:  br.s       IL_0022
17   IL_000d:  nop
18   IL_000e:  ldloc.0
19   IL_000f:  ldloc.1
20   IL_0010:  ldloca.s   i
21   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:  nop
25   IL_001d:  nop
26   IL_001e:  ldloc.1
27   IL_001f:  ldc.i4.1
28   IL_0020:  add
29   IL_0021:  stloc.1
30   IL_0022:  ldloc.1
31   IL_0023:  ldc.i4.s   10
32   IL_0025:  clt
33   IL_0027:  stloc.2
34   IL_0028:  ldloc.2
35   IL_0029:  brtrue.s   IL_000d
36   IL_002b:  ldc.i4.0
37   IL_002c:  stloc.1
38   IL_002d:  br.s       IL_006b
39   IL_002f:  nop
40   IL_0030:  ldc.i4.4
41   IL_0031:  newarr     [mscorlib]System.Object
42   IL_0036:  stloc.3
43   IL_0037:  ldloc.3
44   IL_0038:  ldc.i4.0
45   IL_0039:  ldstr      "row["
46   IL_003e:  stelem.ref
47   IL_003f:  ldloc.3
48   IL_0040:  ldc.i4.1
49   IL_0041:  ldloc.1
50   IL_0042:  box        [mscorlib]System.Int32
51   IL_0047:  stelem.ref
52   IL_0048:  ldloc.3
53   IL_0049:  ldc.i4.2
54   IL_004a:  ldstr      "]="
55   IL_004f:  stelem.ref
56   IL_0050:  ldloc.3
57   IL_0051:  ldc.i4.3
58   IL_0052:  ldloc.0
59   IL_0053:  ldloc.1
60   IL_0054:  callvirt   instance string Test1.Row::get_Item(int32)
61   IL_0059:  stelem.ref
62   IL_005a:  ldloc.3
63   IL_005b:  call       string [mscorlib]System.String::Concat(object[])
64   IL_0060:  call       void [mscorlib]System.Console::WriteLine(string)
65   IL_0065:  nop
66   IL_0066:  nop
67   IL_0067:  ldloc.1
68   IL_0068:  ldc.i4.1
69   IL_0069:  add
70   IL_006a:  stloc.1
71   IL_006b:  ldloc.1
72   IL_006c:  ldc.i4.s   10
73   IL_006e:  clt
74   IL_0070:  stloc.2
75   IL_0071:  ldloc.2
76   IL_0072:  brtrue.s   IL_002f
77   IL_0074:  ret
78 } // end of method Program::Main

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

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

 

c# 索引器

上一篇:C#操作Word


下一篇:VS2015预览版中的C#6.0 新功能(一)