C# в чем смысл или польза индексатора?

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

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

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

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

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

11 ответов


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

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

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

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

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

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

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

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

Надежда эта помощь.


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


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

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


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

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

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


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

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


это реализация оператора индекса [ ].


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

вы, конечно, можете написать коллекцию.Функция GetElement(someIndex) эквивалентна, но это стиль/читаемость.


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

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


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

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


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

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] );