С# в чем смысл или преимущество индексатора?

Выполняя чтение кода и наткнувшись на этот фрагмент, который я раньше не видел:

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

Похоже, он вызывается следующим образом:

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

Мне интересно, где эта функция была бы уместна или что намерение писать в этом стиле. Например, почему это было бы предпочтительнее простого вызова функции?

Ответ 1

См. спецификацию языка, раздел 10.9, которая гласит:

Indexer является членом, который позволяет индексировать объект так же, как массив.

Индексы и свойства очень схожи по понятию, но отличаются следующими способами:

  • Свойство идентифицируется по его имени, тогда как указатель идентифицируется его сигнатурой.
  • Доступ к ресурсу осуществляется с помощью простого имени (§7.5.2) или доступа к члену (§7.5.4), тогда как элемент индексатора обращается через элемент-доступ (§7.5.6.2).
  • Свойство может быть статическим членом, тогда как индекс всегда является членом экземпляра.
  • Получение доступа к объекту соответствует методу без параметров, тогда как get accessor индексатора соответствует методу с тем же формальным списком параметров, что и индекс.
  • Атрибут доступа к объекту соответствует методу с единственным параметром с именем value, в то время как аксессуар набора индексатора соответствует методу с тем же формальным списком параметров, что и индекс, плюс дополнительный параметр с именем value.
  • Это ошибка времени компиляции для аксессора индексатора, чтобы объявить локальную переменную с тем же именем, что и параметр индексатора.
  • В объявлении переопределения свойств доступ к наследуемому свойству осуществляется с использованием базы синтаксиса .P, где P - имя свойства. В переопределяющем объявлении индексатора доступ к наследуемому индексатору осуществляется с использованием базы синтаксиса [E], где E - список выражений, разделенных запятыми.

Ответ 2

Похоже, что многие ответы сосредоточены на том, что такое индексатор, а не на том, почему вы хотели бы использовать его.

Насколько мне известно, вот мотивация использования индексатора:

Вы работаете над классом, который имеет какую-то коллекцию, но вы хотите, чтобы класс отображался пользователям (потребителям класса), как если бы это была коллекция.

Лучший пример, который я могу представить, - это класс DataRow в ADO.NET. Если вы хотите получить значение пятой ячейки DataRow, вы можете использовать DataRow.Item[4] или DataRow[4]. Последняя форма - удобный и логичный ярлык, и это довольно хорошо показывает, почему вы хотите использовать индексатор. Для пользователя DataRow можно рассматривать как просто набор ячеек (хотя это действительно нечто большее), поэтому имеет смысл иметь возможность напрямую получать и устанавливать значения ячеек, не задумываясь о том, что вы на самом деле получают/устанавливают Item.

Надеюсь, что это поможет.

Ответ 3

Во многих случаях синтаксис "index" имеет большой смысл. Это особенно полезно, если SomeClass представляет какую-то коллекцию.

Ответ 4

Это позволяет вам создавать ассоциативные поиски массивов (стиль словаря "a.k.a." ), как вы упомянули в своем вопросе.

И это все. Некоторым людям это нравится, особенно люди, пришедшие с языков, на которых он встроен, например Python или PHP

Ответ 5

Ключевое слово "this" является индексом

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

"Индексаторы позволяют индексировать экземпляры класса или структуры точно так же, как массивы. Индексаторы напоминают свойства, за исключением того, что их аксессоры принимают параметры.

Ответ 6

Возможно, вы уже наткнулись на что-то подобное раньше:

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) - синтаксический сахар, если хотите. Но это также делает намерение понятным.

Ответ 7

Это реализация указательного оператора [ ].

Ответ 8

Это перегрузка оператора. Полезно, если вы пишете класс коллекции, например, если имеет смысл получить к нему доступ с использованием нотации массива, например. Коллекция [someIndex].

Вы могли бы, конечно, написать эквивалентную функцию collection.GetElement(someIndex), но это стиль/читаемость.

Ответ 9

Ну, вы можете использовать этот метод в классе пар ключ-значение.

Я не уверен, что аналогичный класс находится в С#, но в С++ STL есть класс карты, где вы вызываете метод с SomeObject["key"], и он вернет "значение", связанное с этим ключом.

Ответ 10

Что называется Indexer, они позволяют использовать List < > , ArrayList, Dictionary < > и все остальные коллекции, используя синтаксис массива.

Это просто синтаксический сахар, но при правильном использовании он дает некоторую удобочитаемость.

Ответ 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] );