C # в чем смысл или выгода индексатора? - PullRequest
13 голосов
/ 07 января 2010

Чтение некоторого кода и наткнулся на этот фрагмент, которого я раньше не видел:

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

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

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

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

Ответы [ 11 ]

22 голосов
/ 07 января 2010

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

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

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

  • Свойство идентифицируется по его имени, а индексатор - по его подписи.
  • Свойство доступно через простое имя (§7.5.2) или членский доступ (§7.5.4), тогда как элемент indexer доступен через элемент-доступ (§7.5.6.2).
  • Свойство может быть статическим членом, тогда как индексатор всегда является членом экземпляра.
  • Метод доступа get свойства соответствует методу без параметров, а метод доступа get индексатора соответствует методу с тем же списком формальных параметров, что и индексатору.
  • Метод доступа set свойства соответствует методу с единственным параметром с именем value, тогда как метод доступа set индексатора соответствует методу с таким же списком формальных параметров, как индексатор, плюс дополнительный параметр с именем value.
  • Ошибка средства доступа индексатора при объявлении локальной переменной с тем же именем, что и у параметра индексатора.
  • В объявлении переопределяющего свойства доступ к унаследованному свойству осуществляется с использованием синтаксиса base.P, где P - имя свойства. В объявлении переопределенного индексатора доступ к унаследованному индексатору осуществляется с использованием синтаксической базы [E], где E - это список выражений через запятую.
18 голосов
/ 07 января 2010

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

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

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

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

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

6 голосов
/ 07 января 2010

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

3 голосов
/ 07 января 2010

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

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

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

3 голосов
/ 07 января 2010

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

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

1 голос
/ 07 января 2010

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

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

0 голосов
/ 25 января 2015

На мой взгляд, это просто удобство синтаксиса.Где бы вы НЕ использовали бы его:

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] );
0 голосов
/ 07 января 2010

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

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

0 голосов
/ 07 января 2010

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

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

0 голосов
/ 07 января 2010

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

Можно, конечно, написать эквивалент функции collection.GetElement (someIndex), но это стиль / удобочитаемость.

...