• 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:  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方法,这就是索引器为我们带来的便利性,简化了我们变成的方式。

  • 相关阅读:
    数据库设计
    java 的继承,深入理解
    ant 使用笔记
    Effective C++ 精要(第七部分:模板与泛型编程)
    Effective C++ 精要(第八部分:定制new和delete)
    求数组的子数组之和的最大值
    Effective C++ 精要(第四部分:设计与声明)
    STL的容器中存储对象和指针的利和弊
    (zz)Why Memory Barrier
    理解smart pointer之二:如何实现一个smart pointer
  • 原文地址:https://www.cnblogs.com/justinli/p/indexer.html
Copyright © 2020-2023  润新知