Язык программирования C#9 и платформа .NET5. Страница 201
using System.Collections;public class CarCollection : IEnumerable{ private ArrayList arCars = new ArrayList(); // Приведение для вызывающего кода. public Car GetCar(int pos) => (Car) arCars[pos]; // Вставка только объектов Car. public void AddCar(Car c) { arCars.Add(c); } public void ClearCars() { arCars.Clear(); } public int Count => arCars.Count; // Поддержка перечисления с помощью foreach. IEnumerator IEnumerable.GetEnumerator() => arCars.GetEnumerator();}Тем не менее, класс специальной коллекции ничего не делает для решения проблемы с накладными расходами по упаковке/распаковке. Даже если создать специальную коллекцию по имени
IntCollectionSystem.Int32System.ArrayArrayListpublic class IntCollection : IEnumerable{ private ArrayList arInts = new ArrayList();<b> // Получение int (выполняется распаковка).</b> public int GetInt(int pos) => (int)arInts[pos];<b> // Вставка int (выполняется упаковка).</b> public void AddInt(int i) { arInts.Add(i); } public void ClearInts() { arInts.Clear(); } public int Count => arInts.Count; IEnumerator IEnumerable.GetEnumerator() => arInts.GetEnumerator();}Независимо от того, какой тип выбран для хранения целых чисел, в случае применения необобщенных контейнеров затруднительного положения с упаковкой избежать невозможно.
Первый взгляд на обобщенные коллекции
Когда используются классы обобщенных коллекций, все описанные выше проблемы исчезают, включая накладные расходы на упаковку/распаковку и отсутствие безопасности в отношении типов. К тому же необходимость в создании специального класса (обобщенной) коллекции становится довольно редкой. Вместо построения уникальных классов, которые могут хранить объекты людей, автомобилей и целые числа, можно задействовать класс обобщенной коллекции и указать тип хранимых элементов. Добавьте в начало файла
Program.csusingusing System.Collections.Generic;Взгляните на показанный ниже метод (добавленный в конец файла
Program.csList<T>System.Collection.Genericstatic void UseGenericList(){ Console.WriteLine("***** Fun with Generics *****\n");<b> // Этот объект List<> может хранить только объекты Person.</b> List<Person> morePeople = new List<Person>(); morePeople.Add(new Person ("Frank", "Black", 50)); Console.WriteLine(morePeople[0]);<b> // Этот объект ListO может хранить только целые числа.</b> List<int> moreInts = new List<int>(); moreInts.Add(10); moreInts.Add(2); int sum = moreInts[0] + moreInts[1];<b> // Ошибка на этапе компиляции! Объект Person</b><b> // не может быть добавлен в список элементов int!</b> // moreInts.Add(new Person());}Первый контейнер
List<T>PersonList<T>ArrayList• Обобщения обеспечивают лучшую производительность, т.к. лишены накладных расходов по упаковке/распаковке, когда хранят типы значений.
• Обобщения безопасны в отношении типов, потому что могут содержать только объекты указанного типа.
• Обобщения значительно сокращают потребность в специальных типах коллекций, поскольку при создании обобщенного контейнера указывается "вид типа".