Язык программирования C#9 и платформа .NET5
Индексаторы являются еще одной формой "синтаксического сахара", учитывая то, что такую же функциональность можно получить с применением "нормальных" открытых методов наподобие
илиAddPerson(). Тем не менее, поддержка индексаторных методов в специальных типах коллекций обеспечивает хорошую интеграцию с инфраструктурой библиотек базовых классов .NET Core.GetPerson()Несмотря на то что создание индексаторных методов является вполне обычным явлением при построении специальных коллекций, не забывайте, что обобщенные типы предлагают такую функциональность в готовом виде. В следующем методе используется обобщенный список
объектовList<T>. Обратите внимание, что индексаторPersonможно просто применять непосредственно:List<T>using System.Collections.Generic;static void UseGenericListOfPeople(){List<Person> myPeople = new List<Person>();myPeople.Add(new Person("Lisa", "Simpson", 9));myPeople.Add(new Person("Bart", "Simpson", 7));// Изменить первый объект лица с помощью индексатора.myPeople[0] = new Person("Maggie", "Simpson", 2);// Получить и отобразить каждый элемент, используя индексатор.for (int i = 0; i < myPeople.Count; i++){Console.WriteLine("Person number: {0}", i);Console.WriteLine("Name: {0} {1}",myPeople[i].FirstName, myPeople[i].LastName);Console.WriteLine("Age: {0}", myPeople[i].Age);Console.WriteLine();}}Индексация данных с использованием строковых значений
В текущей версии класса
определен индексатор, позволяющий вызывающему коду идентифицировать элементы с применением числовых значений. Однако вы должны понимать, что это не требование индексаторного метода. Предположим, что вы предпочитаете хранить объектыPersonCollection, используя типPerson, а неSystem.Collections.Generic.Dictionary<TKey,TValue>. Поскольку типыArrayListразрешают доступ к содержащимся внутри них элементам с применением ключа (такого как фамилия лица), индексатор можно было бы определить следующим образом:Dictionaryusing System.Collections;using System.Collections.Generic;namespace SimpleIndexer{public class PersonCollectionStringIndexer : IEnumerable{private Dictionary<string, Person> listPeople =new Dictionary<string, Person>();// Этот индексатор возвращает объект лица на основе строкового индекса.public Person this[string name]{get => (Person)listPeople[name];set => listPeople[name] = value;}public void ClearPeople(){listPeople.Clear();}public int Count => listPeople.Count;IEnumerator IEnumerable.GetEnumerator() => listPeople.GetEnumerator();}}Теперь вызывающий код способен взаимодействовать с содержащимися внутри объектами
:PersonConsole.WriteLine("***** Fun with Indexers *****\n");PersonCollectionStringIndexer myPeopleStrings =new PersonCollectionStringIndexer();myPeopleStrings["Homer"] =new Person("Homer", "Simpson", 40);myPeopleStrings["Marge"] =new Person("Marge", "Simpson", 38);// Получить объект лица Homer и вывести данные.Person homer = myPeopleStrings["Homer"];Console.ReadLine();И снова, если бы обобщенный тип
, напрямую, то функциональность индексаторного метода была бы получена в готовом виде без построения специального необобщенного класса, поддерживающего строковый индексатор. Тем не менее, имейте в виду, что тип данных любого индексатора будет основан на том, как поддерживающий тип коллекции позволяет вызывающему коду извлекать элементы.Dictionary<TKey, TValue>Перегрузка индексаторных методов
Индексаторные методы могут быть перегружены в отдельном классе или структуре. Таким образом, если имеет смысл предоставить вызывающему коду возможность доступа к элементам с применением числового индекса или строкового значения, то в одном типе можно определить несколько индексаторов. Например, в ADO.NET (встроенный API-интерфейс .NET для доступа к базам данных) класс
t поддерживает свойство по имениDataSe, которое возвращает строго типизированную коллекциюTables. В свою очередь типDataTableCollectionопределяет три индексатора для получения и установки объектовDataTableCollection— по порядковой позиции, по дружественному строковому имени и по строковому имени с дополнительным пространством имен:DataTable