Литмир - Электронная Библиотека
A
A

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

}

Тем не менее, класс специальной коллекции ничего не делает для решения проблемы с накладными расходами по упаковке/распаковке. Даже если создать специальную коллекцию по имени

IntCollection
, которая предназначена для работы только с элементами
System.Int32
, то все равно придется выделять память под объект какого-нибудь вида, хранящий данные (например,
System.Array
и
ArrayList
):

public class IntCollection : IEnumerable

{

  private ArrayList arInts = new ArrayList();

<b>  // Получение int (выполняется распаковка).</b>

  public int GetInt(int pos) =&gt; (int)arInts[pos];

<b>  // Вставка int (выполняется упаковка).</b>

  public void AddInt(int i)

  {

    arInts.Add(i);

  }

  public void ClearInts()

  {

    arInts.Clear();

  }

  public int Count =&gt; arInts.Count;

  IEnumerator IEnumerable.GetEnumerator() =&gt; arInts.GetEnumerator();

}

Независимо от того, какой тип выбран для хранения целых чисел, в случае применения необобщенных контейнеров затруднительного положения с упаковкой избежать невозможно.

Первый взгляд на обобщенные коллекции

Когда используются классы обобщенных коллекций, все описанные выше проблемы исчезают, включая накладные расходы на упаковку/распаковку и отсутствие безопасности в отношении типов. К тому же необходимость в создании специального класса (обобщенной) коллекции становится довольно редкой. Вместо построения уникальных классов, которые могут хранить объекты людей, автомобилей и целые числа, можно задействовать класс обобщенной коллекции и указать тип хранимых элементов. Добавьте в начало файла

Program.cs
следующий оператор
using
:

using System.Collections.Generic;

Взгляните на показанный ниже метод (добавленный в конец файла

Program.cs
), в котором используется класс
List&lt;T&gt;
(из пространства имен
System.Collection.Generic
) для хранения разнообразных видов данных в строго типизированной манере (пока не обращайте внимания на детали синтаксиса обобщений):

static void UseGenericList()

{

  Console.WriteLine(&quot;***** Fun with Generics *****\n&quot;);

<b>  // Этот объект List&lt;&gt; может хранить только объекты Person.</b>

  List&lt;Person&gt; morePeople = new List&lt;Person&gt;();

  morePeople.Add(new Person (&quot;Frank&quot;, &quot;Black&quot;, 50));

  Console.WriteLine(morePeople[0]);

<b>  // Этот объект ListO может хранить только целые числа.</b>

  List&lt;int&gt; moreInts = new List&lt;int&gt;();

  moreInts.Add(10);

  moreInts.Add(2);

  int sum = moreInts[0] + moreInts[1];

<b>  // Ошибка на этапе компиляции! Объект Person</b>

<b>  // не может быть добавлен в список элементов int!</b>

  // moreInts.Add(new Person());

}

Первый контейнер

List&lt;T&gt;
способен содержать только объекты
Person
. По этой причине выполнять приведение при извлечении элементов из контейнера не требуется, что делает такой подход более безопасным в отношении типов. Второй контейнер
List&lt;T&gt;
может хранить только целые числа, размещенные в стеке; другими словами, здесь не происходит никакой скрытой упаковки/распаковки, которая имеет место в необобщенном типе
ArrayList
. Ниже приведен краткий перечень преимуществ обобщенных контейнеров по сравнению с их необобщенными аналогами.

• Обобщения обеспечивают лучшую производительность, т.к. лишены накладных расходов по упаковке/распаковке, когда хранят типы значений.

• Обобщения безопасны в отношении типов, потому что могут содержать только объекты указанного типа.

• Обобщения значительно сокращают потребность в специальных типах коллекций, поскольку при создании обобщенного контейнера указывается "вид типа".

201
{"b":"847442","o":1}