13

阅读一些代码并偶然发现了我以前从未见过的这段代码:

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

它看起来像这样调用:

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

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

4

11 回答 11

23

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

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

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

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

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

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

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

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

希望有帮助。

于 2010-01-06T23:10:32.910 回答
6

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

于 2010-01-06T22:34:15.753 回答
3

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

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

于 2010-01-06T22:34:44.817 回答
3

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

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

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

于 2010-01-06T22:35:29.137 回答
1

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

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) 这样的函数的一种简写方式——如果你愿意的话,它是语法糖。但它也清楚地表明了意图。

于 2010-01-06T22:37:19.670 回答
0

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

于 2010-01-06T22:34:54.213 回答
0

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

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

于 2010-01-06T22:34:59.457 回答
0

好吧,您可以在键值对类中使用此方法。

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

于 2010-01-06T22:35:31.200 回答
0

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

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

于 2010-01-06T22:35:42.417 回答
0

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

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] );
于 2015-01-25T19:45:28.220 回答