С# в чем смысл или преимущество индексатора?
Выполняя чтение кода и наткнувшись на этот фрагмент, который я раньше не видел:
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] );