【问题标题】:C# what is the point or benefit of an indexer?C# 索引器的意义或好处是什么?
【发布时间】:2011-01-02 06:37:57
【问题描述】:

读了一些代码,偶然发现了这个我以前没见过的sn-p:

public SomeClass {
  public someInterface this[String strParameter] {
    get {
      return SomeInternalMethod(strParameter);
    }
  }
}

貌似是这样调用的:

SomeClass _someClass = new SomeClass();
SomeInterface returnedValue = _someClass["someString"];

我感兴趣的是这个函数在哪里是合适的,或者用这种风格写作的意图是什么。例如,为什么这比简单地调用函数更受欢迎?

【问题讨论】:

标签: c# methods indexer


【解决方案1】:

在许多情况下,“索引”语法很有意义。如果 SomeClass 表示某种集合,则它特别有用。

【讨论】:

    【解决方案2】:

    正如您在问题中提到的那样,它允许您进行关联数组查找(也称为“字典样式”)。

    这就是重点。有些人喜欢这样,尤其是那些来自内置它的语言的人,比如 Python 或 PHP

    【讨论】:

      【解决方案3】:

      它是索引运算符[ ] 的实现。

      【讨论】:

        【解决方案4】:

        这是一个运算符重载。如果您正在编写一个集合类,例如使用数组表示法访问它是有意义的,例如集合[someIndex]。

        您当然可以编写一个等价的 collection.GetElement(someIndex) 函数,但它是一种风格/可读性的东西。

        【讨论】:

          【解决方案5】:

          “this”关键字是一个索引器

          来自http://msdn.microsoft.com/en-us/library/6x16t2tx.aspx

          “索引器允许类或结构的实例像数组一样被索引。索引器类似于属性,只是它们的访问器带有参数。”

          【讨论】:

          • 什么意思:“this”关键字是索引器?
          【解决方案6】:

          你可以在键值对类中使用这个方法。

          我不确定 c# 中的类似类是什么,但在 c++ STL 中,有一个 map 类,您可以在其中使用 SomeObject["key"] 调用方法,它将返回与该键关联的“值”。

          【讨论】:

          • C# 中的类似类是 System.Collections.Generic.Dictionary(除了 Dictionary 使用哈希查找,而 map 对键进行排序)
          【解决方案7】:

          这称为索引器,它们允许您使用 List、ArrayList、Dictionary 和所有其他使用数组语法的集合。

          它只是语法糖,但如果使用得当,它会提供一些可读性。

          【讨论】:

            【解决方案8】:

            参见语言规范,第 10.9 节,其中指出:

            Indexer 是使对象能够以与数组相同的方式被索引的成员。

            索引器和属性在概念上非常相似,但在以下方面有所不同:

            • 属性由其名称标识,而索引器由其签名标识。
            • 属性通过简单名称(第 7.5.2 节)或成员访问(第 7.5.4 节)访问,而索引器元素通过元素访问(第 7.5.6.2 节)访问。李>
            • 属性可以是静态成员,而索引器始终是实例成员。
            • 属性的 get 访问器对应于没有参数的方法,而索引器的 get 访问器对应于具有与索引器相同的形参列表的方法。
            • 属性的 set 访问器对应于具有单个名为 value 的参数的方法,而索引器的 set 访问器对应于具有与索引器相同的形参列表的方法,加上一个名为 value 的附加参数。李>
            • 索引器访问器声明与索引器参数同名的局部变量是编译时错误。
            • 在覆盖属性声明中,使用语法 base.P 访问继承的属性,其中 P 是属性名称。在覆盖索引器声明中,使用语法 base[E] 访问继承的索引器,其中 E 是逗号分隔的表达式列表。

            【讨论】:

            • 我知道我不应该劫持这个,但也许你可以写博客为什么没有静态索引器?当我看到它们不存在时,我感到很震惊,因为这是一种很好的速记方式。 (在 Jon 提出好的 Encoding["UTF8"] 示例之前 :))
            • 我刚刚检查了设计说明存档,其中没有任何内容可以证明不使用静态索引器的决定。因此,对于为什么我们没有功能,我必须回到我通常的解释:没有人认为花钱让它成为现实是一个足够好的想法。我想同样的解释也解释了为什么索引器不能是通用的。
            • 酷 :) “默认”解释的好处是它并没有完全关闭这一切可能的大门。我不知道这个功能有多“重”(我不会说“但这只是一个很小的改变!”而不知道编译器和 CLR 实际工作的方式),但它比“我们没有做”要好因为 X、Y 和 Z 使得它永远不可能实现”。
            • 很棒的信息 - 我不知道它被称为索引器,所以我不知道从哪里开始寻找它的定义。我想我对为什么作者使用带有字符串参数的只读索引器感到困惑。如果它是一个 int 我会得到它,因为你可以将它与循环等一起使用。使用字符串参数提供了一个字典类型结构,但它是只读的,所以它真的感觉像一个方法,因为你不能传递一个值。跨度>
            【解决方案9】:

            您之前可能已经偶然发现过类似的东西:

            var myList = new List<string>();
            myList.Add("One");
            myList.Add("Two");
            myList.Add("Three");
            
            for(int i = 0; i < myList.Count; i++) {
                string s = myList[i];
            }
            

            索引器是实现集合的对象的“主键”。这只是编写像 .GetValue(index) 这样的函数的一种简写方式——如果你愿意的话,它是语法糖。但它也清楚地表明了意图。

            【讨论】:

              【解决方案10】:

              似乎很多答案都集中在索引器是什么,而不是为什么要使用索引器。

              就我而言,这是使用索引器的动机:

              您正在处理一个具有某种集合的类,但您希望该类向用户(该类的消费者)显示它就像 一个集合。

              我能想到的最好的例子是 ADO.NET 中的 DataRow 类。如果要获取DataRow 的第五个单元格的值,可以使用DataRow.Item[4]DataRow[4]。后一种形式是一种方便且合乎逻辑的快捷方式,它很好地展示了您为什么要使用索引器。对于用户来说,DataRow 可以被认为只是一个单元格的集合(尽管它实际上不止于此),因此能够直接获取和设置单元格值是有意义的,而不必记住你实际上正在获取/设置Item

              希望对您有所帮助。

              【讨论】:

                【解决方案11】:

                在我看来,这只是一种语法便利。 您会在哪里使用它:

                public SomeClass {
                  private int[] nums;
                  public GetVal this[int ind] {
                    get {
                      return nums[ind]; // this is pointless since array is already indexed
                    }
                  }
                }
                

                您将从哪里受益

                public Matrix {
                  private Dictionary<string, double> matrixData; // Matrix indecies, value
                  public double this[int row, int col] {
                    get {
                      return matrixData[string.Format("{0},{1}", row, col)];
                    }
                  }
                }
                

                如您所见,出于某种原因,您的数据是一个使用字符串键索引的字典,您希望使用两个整数索引来调用它,但仍不想更改您的数据类型:

                Matrix m = new Matrix();
                ...
                Console.WriteLine( m[1,2] );
                

                【讨论】:

                  猜你喜欢
                  • 2023-04-07
                  • 1970-01-01
                  • 2015-03-16
                  • 2018-06-21
                  • 1970-01-01
                  • 1970-01-01
                  • 2010-09-13
                  • 1970-01-01
                  • 2022-11-25
                  相关资源
                  最近更新 更多