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