**Требования:** 1. Придерживайтесь принципа DRY (Don’t repeat yourself). 2. Используйте комментарии и xml-комментарии. 3. Обработка и генерация исключительных ситуаций на ваше усмотрение. 1. Измените поведение смены идентификатора витрины класса-контейнера: - Создайте делегат, информирующий о смене идентификатора. - Крайне желательно использовать готовые делегаты. - Для информирования о смене идентификатора, передается ссылка на саму витрину. - Используя методы расширения, добавьте метод в обобщенный товар, соответствующий сигнатуре делегата, описанного выше; - Метод расширения можно перегрузить для случая, когда меняется позиция товара на витрине; - Методы расширения, это именно методы расширения, а не просто добавленные в класс новые функции; - Обобщенный товар, это не новый класс, который требуется разработать, вспомните об обобщенном классе-контейнеры и функций переинициализации штрихкода (в каких двух местах они раньше вызывались). - Обеспечьте правильный вызов, подписку и отписку делегата смена идентификатора витрины; - Для информации, товару нужно знать на какой идентификатор сменила витрина и в какой позиции сейчас товар. 2. Создайте запакованный класс производный от `EventArgs`, хранящий информацию по-старому и новому идентификатору: - Добавьте в интерфейс товара событие смены его идентификатора, и реализуйте его в абстрактном классе товара. - Делегат должен быть типа: `EventHandler`, где `T` – ваш производный класс от `EventArgs`; - Обеспечьте правильную подписку и отписку от события в классе-контейнере, позволяющую правильно рассчитать новый штрих-код товара на складе при смене его идентификатора. 3. Свяжите функции сортировки товара через новую функцию, с использованием делегатов. - Определите общую часть кода в методах сортировки; - Вынесите общую часть кода в новый метод; - Отличающуюся логику в методе замените делегатом, нужной сигнатуры. 4. Свяжите функции поиска позиции товара через новую функцию, с использованием делегатов. - Определите общую часть кода в функциях поиска; - Вынесите общую часть кода в новую функцию; - Отличающуюся логику в функции замените делегатом, нужной сигнатуры. 5. Протестируйте работу программы. ## Псевдокод ```cs static void TestLab4() { Console.Clear(); var lab4Data = new List<Товароподобный> { new ОбычныйТовар(3000, "ВОЙНА И МИРЬ III", "Л.Н. Толстой", 1867, 300000), new ОбычныйТовар(1000, "ВОЙНА И МИРЬ I", "Л.Н. Толстой", 1863, 1000000), new ОбычныйТовар(2000, "ВОЙНА И МИРЬ II", "Л.Н. Толстой", 1865, 200000), new КонечныйТовар(5555, "Хранители", "С. Маккоауд", 2008, 2071), new КонечныйТовар(6666, "Понимание комикса", "A. Шпигельман", 1990, 860) }; ВитринаТовароподобных а = (7, 1); // витрина на 7 позиций с 1м идентификатором foreach (var товар in lab4Data) { a. Push(товар); } a. OrderByName(); var sample1 = new КонечныйТовар(7777, "Ходячие мертвецы", "P. Кирман", 2003, 2257); var sample2 = new ОбычныйТовар(4000, "ВОЙНА И МИРЪ IV", "Л.н. Толстой", 1869, 400000); a[5] = samplel; a[6] = sample2; // смена ID a. Id = 2; sample1.Id++; sample2.Id++; // Каждый товар должен правильно отображать штрих код: // - ОбычныйТовар на витрине отображает штрихкод с позицией и ID витрины // - КонечныйТовар, отображает только ID товара, обрамленный * Console.WriteLine(a); } ```