Разработать программное обеспечение для терминала формирования ассортимента товаров (витрины). Предусмотреть вывод информации по ассортименту, каждый экземпляр товара имеет свой уникальный код. Код представляет собой числовое значение и его строковый вид в формате штрихкода. Витрина представлена в виде последовательности ячеек (полок) для хранения. В каждой ячейке может храниться максимум один экземпляр товара. При старте программы ассортимент заполнен товаром частично.  
**Терминал позволяет:**
- Выставлять/снимать товар на склад;
- Выводить информацию по товару, в отсортированном виде;
- Менять товары местами, заменять на новый;
- Изменять стандартный способ вывода кода товара;
- Определять наличие товара, по коду или наименованию.
  
**Требования:**
1. Запрещается использовать обработку исключительных ситуаций и генерировать исключения.
2. Каждый класс должен быть оформлен в отдельном файле.
3. Придерживайтесь принципа DRY (Don’t repeat yourself).
4. Обязательно наличие комментариев и xml-комментариев.
## Техническое задание
### Раздел 1
Создать в решении новую библиотеку классов для товара, подключить в зависимостях библиотеку для работы со штрихкодами из ЛР1.  
#### Часть 1
Товар описать в виде абстрактного класса, без виртуальных методов:
- Предусмотреть возможность задавать идентификатор товара и его наименование;
	- Помимо идентификатора, товар должен содержать информацию по штрихкоду, который должен обязательно в каждый раз заново инициализироваться при смене идентификатора товара (Поведение связано с заданиями в других лабораторных);
	- Требуется дать возможность изменять штрихкод и идентификатор товара;
	- Изменять наименование товара вне класса, на свое усмотрение.
- Перегрузить функцию «`ToString()`» для получения информации по типу товара, наименованию, информации от производных классов и штрихкоду;
	- Тип товара переопределяется в производных классах.
- Формат вывода информации:  
	![Формат вывода информации](../../Pictures/ЛБ02_01.%20Формат%20вывода%20информации.png)  
	Свойство "Тип товара" не должно быть доступно классам, не являющимися производными от абстрактного класса товара
- Класс не должен содержать открытых методов и полей («Класс-Модель»), но может позволять взаимодействовать с информацией по наименованию, коду и способу вывода данного кода.
#### Часть 2
Создать класс, производный от абстрактного, согласно своему варианту (вариант А из курсовой по ООП):
- Добавить как минимум 3 новых свойства, описывающих класс согласно вашему варианту;
- Предоставить базовому классу информацию по его типу товара и выводимой информации на консоль (см. формат вывода ч.1).
### Раздел 3
Создать в решении новую библиотеку классов для витрины, подключить в зависимостях библиотеку для работы со штрихкодами из ЛР1 и товарами, раздела 1 этой лабораторной.
#### Часть 1
Витрину представить как класс-контейнер с возможностью выставлять фиксированное количество товара:
- У каждой витрины есть свой уникальный числовой код (идентификатор);
- Класс-контейнер взаимодействует с товарами только через класс раздела 1 части 1.
  
У класса должен быть только один закрытый конструктор:
- Для создания экземпляров класса, запрещается использовать: синглтон, фабричные методы, абстрактные фабрики (паттерны проектирования) и рефлексию (`System.Reflection`);
- Способ создания объектов класса должен быть описан только в самом классе витрины;
- При создании объектов класса должно явно задаваться количество элементов контейнера, для примера: Витрина **v = 10**, `var v = (Витрина)10`
#### Часть 2
Реализовать функционал получения нужного товара по его порядковому номеру (индексу) через оператор индексации \[\]:
- При этом обращение по индексу должно соответствовать принципу, как если бы товар снимался из «ячейки», и его можно было не возвращать обратно на место;
- Получение товара по индексу, должно учитывать, что место в позиции свободное;
- Для случая, если мы выходим за пределы массива, никаких усложненных действий не требуется:
	- Для получения, вернуть просто вернуть `null`;
	- Для установки, выйти (`return`).
  
Реализовать методы:
- Добавления (в первую пустую ячейку и в конкретную позицию), удаления (аналогично), замены и перестановки товара на витрине, связав их с индексатором класса;
- Поиска позиции товара по его идентификатору;
- Поиска позиции товара по его наименованию;
- Сортировки товаров на витрине по идентификатору;
- Сортировки товаров на витрине по наименованию;
  
Перегрузить функцию «`ToString()`» для получения информации по всем элементам, хранящимся в контейнере:
- Учитывать пустые ячейки.
#### Часть 3
Реализовать возможность добавления к текстовой информации штрихкода товара, информации по идентификатору витрины и номеру позиции на витрине:
- Идентификатор витрины и позиция товара не влияют на сам идентификатор товара;
- Конечная текстовая информация штрихкода товара на витрине должны быть в формате: «ID товара» «ID витрины» «Позиция»;
	- Для примера: «1000 10 20», где: 
		- 1000 - «ID товара»
		- 10 - «ID витрины»
		- 20 - позиция товара на витрине.
- Штрихкод товара на витрине должен меняться автоматически, когда:
	- меняется его позиция на витрине;
	- меняется идентификатор витрины;
	- товар перекладывают на другую витрину;
	- штрихкод сбрасывается до «ID товара», если менять сам идентификатор товара;
	- Во всех случаях штрихкод должен полностью пересоздаваться.
## Псевдокод
```cs
static void TestLab2()
{
	Console.WriteLine("".PadLeft(80, '='));
	Витрина showcase = 5; // Способ создания витрины на 5 мест
	
	var sample = new КонкретныйТовар(1000, "ВОЙНА И МИРЬ I", "Л.н. Толстой", 1863, 1000000); 
	var lab2Data = new List<Товар>
	{
		new КонкретныйТовар(3000, "ВОЙНА И МИРЬ III", "Л.Н. Толстой", 1867, 300000), 
		new КонкретныйТовар(2000, "ВОЙНА И МИРЬ II", "Л.Н. Толстой", 1865, 200000), 
		new КонкретныйТовар(4000, "ВОЙНА И МИРЬ IV", "Л.Н. Толстой", 1869, 400000)
	};
	
	foreach (var product in lab2Data)
	{
		showcase.Push(product); // допускаемый способ закидывания товара на витрину в пустое место
	}
	showcase[4] = sample; //прямая отправка товара на нужную позицию витрины
	
	sample.Id++; // Можно изменять идентификатор, при этом на витрине товар утратит свой уникальный штрих код
	Console.WriteLine(sample);
	
	showcase.OrderByName(); // Обязательная сортировка, она же может чинить штрихкоды товаров, т.к. фактически происходит изменение позиций товаров на витрине.
	showcase.Id++; // можно менять ID витрины 
	Console.WriteLine(showcase); // приведение к строке витрины
}
```