Читаем Интернет-журнал "Домашняя лаборатория", 2007 №9 полностью

public void TestConstraint ()

{

    OneLinkList list1 = new OneLinkList

        ();

    list1.add(33, "thirty three"); list1.add (22, "twenty two");

    if (list1.findstart(33)) Console.WriteLine ("33 — найдено!");

    else Console.WriteLine("33 — не найдено!");

    if (list1.findstart(22)) Console.WriteLine ("22 — найдено!");

    else Console.WriteLine("22 — не найдено!");

    if (list1.findstart(44)) Console.WriteLine ("44 — найдено!");

    else Console.WriteLine("44 — не найдено!");

    Person pers1 = new Person("Савлов", 25, 1500);

    Person pers2 = new Person("Павлов", 35, 2100);

    OneLinkList list2 = new OneLinkList

         < string, Person>();

    list2.add("Савл", pers1); list2.add("Павел", pers2);

    if (list2.findstart("Павел")) Console.WriteLine ("Павел — найдено!");

    else Console.WriteLine("Павел — не найдено!");

    if (list2.findstart("Савл")) Console.WriteLine ("Савл — найдено!");

    else Console.WriteLine("Савл — не найдено!");

    if (list2.findstart("Иоанн")) Console.WriteLine ("Иоанн — найдено!");

    else Console.WriteLine("Иоанн — не найдено!");

    Person pers3 = new Person("Иванов", 33, 3000);

    list2.add("Иоанн", pers3); list2.start ();

    Person pers = list2.Item(); pers.PrintPerson();

    list2.findstart("Иоанн"); pers = list2.Item();

        pers.PrintPerson();

}



Рис. 22.5.Поиск в списке с ограниченной универсальностью


Обратите внимание на строки, где создаются два списка:

OneLinkList list1 = new OneLinkList();

OneLinkList list2 = new OneLinkList< string, Person>();

У списка list1 ключи имеют тип int, у списка list2 — string. Заметьте, оба фактических типа, согласно обязательствам, реализуют интерфейс IComparable, у первого списка тип элементов — string, у второго — Person. Все работает прекрасно. Вот результаты вычислений по этой процедуре:


Как справиться с арифметикой

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

Как уже говорилось, наличие ограничения операции, где можно было бы указать, что над элементами определена операция +, решало бы проблему. Но такого типа ограничений нет. Хуже того, нет и интерфейса INumeric, аналогичного IComparable, определяющего метод сложения Add. Так что нам не может помочь и ограничение наследования.

Вот один из возможных выходов, предлагаемых в такой ситуации. Стратегия следующая: определим абстрактный универсальный класс Calc с методами, выполняющими вычисления. Затем создадим конкретизированных потомков этого класса. В классе, задающем список с суммированием, введем поле класса Calc. При создании экземпляров класса будем передавать фактические типы ключа и элементов, а также соответствующий калькулятор, но уже не как тип, а как аргумент конструктора класса. Этот калькулятор, согласованный с типом элементов, и будет выполнять нужные вычисления. Давайте приступим к реализации этой стратегии. Начнем с определения класса Calc;

public abstract class Calc

{

    public abstract T Add(T a, T b);

    public abstract T Sub(T a, T b);

    public abstract T Mult(T a, T b);

    public abstract T Div(T a, T b);

}

Наш абстрактный универсальный класс определяет четыре арифметические операции. Давайте построим трех его конкретизированных потомков:

Перейти на страницу:

Похожие книги