Шрифт:
Интервал:
Закладка:
Индексаторы являются еще одной формой "синтаксического сахара", учитывая то, что такую же функциональность можно получить с применением "нормальных" открытых методов наподобие AddPerson() или GetPerson(). Тем не менее, поддержка индексаторных методов в специальных типах коллекций обеспечивает хорошую интеграцию с инфраструктурой библиотек базовых классов .NET Core.
Несмотря на то что создание индексаторных методов является вполне обычным явлением при построении специальных коллекций, не забывайте, что обобщенные типы предлагают такую функциональность в готовом виде. В следующем методе используется обобщенный список 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. Поскольку типы Dictionary разрешают доступ к содержащимся внутри них элементам с применением ключа (такого как фамилия лица), индексатор можно было бы определить следующим образом:
using System.Collections;
using System.Collections.Generic;
namespace SimpleIndexer
{
public class PersonCollectionStringIndexer : IEnumerable
(window.adrunTag = window.adrunTag || []).push({v: 1, el: 'adrun-4-390', c: 4, b: 390}){
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();
}
}
Теперь вызывающий код способен взаимодействовать с содержащимися внутри объектами Person:
Console.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 для доступа к базам данных) класс DataSet поддерживает свойство по имени Tables, которое возвращает строго типизированную коллекцию DataTableCollection. В свою очередь тип DataTableCollection определяет три индексатора для получения и установки объектов DataTable — по порядковой позиции, по дружественному строковому имени и по строковому имени с дополнительным пространством имен:
- Понимание SQL - Мартин Грубер - Базы данных