Как правильно писать тесты 46 Цикл разработки 46 Структура проекта с тестами 51 Утверждения (Asserts) 52 Утверждения в форме ограничений 54 Категории 56

Вид материалаТесты

Содержание


Создание обобщенных делегатов
Несколько слов о вложенных делегатах
Закончить реализацию.
Закончить реализацию.
Проверить список на примере хранения данных о работниках Employee, характеризующихся именем
Проверить, что списки сортируемы.
Подобный материал:
1   ...   39   40   41   42   43   44   45   46   47

Создание обобщенных делегатов




Наконец, что не менее важно, .NET 2.0 позволяет определять обобщенные типы делегата. Предположим, например, что требуется определить делегат, который сможет вызывать любой метод, возвращающий void и принимающий один аргумент. Если аргумент может меняться, это можно учесть с помощью параметра типа. Для примера рассмотрим следующий программный код (обратите внимание на то, что целевые объекты делегата регистрируются как с помощью “традиционного” синтаксиса делегата, так и с помощью группового преобразования метода).


namespace GenericDelegate

{

// Этот обобщенный делегат может вызвать любой метод,

// возвращающий void и принимающий один параметр.

public delegate void MyGenericDelegate(T arg);


class Program

{

static void Main(string[] args)

{

Console.WriteLine("***** Обобщенные делегаты *****\n");


// Регистрация цели с помощью 'традиционного'

// синтаксиса делегата.

MyGenericDelegate strTarget =

new MyGenericDelegate(StringTarget);

strTarget("Некоторые строковые данные");


// Регистрация цели с помощью

// группового преобразования метода.

MyGenericDelegate intTarget = IntTarget;

intTarget(9);

Console.ReadLine();

}


static void StringTarget(string arg)

{

Console.WriteLine("arg в верхнем регистре: {0}",

arg.ToUpper());

}


static void IntTarget(int arg)

{

Console.WriteLine("++arg: {0}", ++arg);

}

}

}


Обратите внимание на то, что MyGenericDelegate определяет один параметр типа, представляющий аргумент, отправляемый целевому объекту делегата. При создании экземпляра этого типа требуется конкретизировать значение параметра типа, а также имя метода, вызываемого делегатом. Так, если вы укажете строковый тип, то отправите целевому методу строковое значение.


// Создание экземпляра MyGenericDelegate

// со значением string для параметра типа.

MyGenericDelegate strTarget =

new MyGenericDelegate(StringTarget);

strTarget("Некоторые строковые данные");


С учетом формата объекта strTarget метод StringTarget() должен теперь получить в качестве параметра одну строку.


static void StringTarget(string arg)

{

Console.WriteLine("arg в верхнем регистре: {0}", arg.ToUpper());

}


Несколько слов о вложенных делегатах




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


// Вложенные обобщенные делегаты могут иметь доступ к параметрам

// обобщенного типа-контейнера.

public class MyList

{

private List listOfData = new List();

public delegate void ListDelegate(T arg);

}


Задачи


1. Создать обобщенный список DisposableList, ведущий себя как IList, с ограничением на элементы, которые обязательно должны реализовывать интерфейс IDisposable.


2. Создать односвязный сортируемый список, состоящий из узлов Node. Каждый узел параметризован типом, который он содержит. Каждый узел должен обеспечивать возможность сравнения с другим узлом списка. Каждый узел дает информацию о следующем узле, идущим за ним.

Объявление класса узла:

public class Node : IComparable> where T : IComparable

{

// фрагменты реализации

private T data;

private Node next = null;

private Node prev = null;



public Node(T data) {…}



public T Data { … }

public Node Next {…}



public Node Add(Node newNode) {…}

public override string ToString() {…}

}

Закончить реализацию.


Головной узел хранится в объекте класса

LinkedList: какому ограничению должен удовлетворять класс?

{

private Node headNode = null;


//Класс обладает методами:

public void Add(T data) {…}

public override string ToString( ) {…}


//а также индексатором

public T this[int index] {…}

}

Закончить реализацию.


Проверить список на примере случайных целых чисел:


LinkedList myLinkedList = new LinkedList( );

Random rand = new Random( );

Console.Write("Adding: ");

for (int i = 0; i < 10; i++)

{

int nextInt = rand.Next(10);

Console.Write("{0} ", nextInt);

myLinkedList.Add(nextInt);

}


Проверить список на примере хранения данных о работниках Employee, характеризующихся именем:


LinkedList employees = new LinkedList( );

employees.Add(new Employee("Douglas"));

employees.Add(new Employee("Paul"));

employees.Add(new Employee("George"));

employees.Add(new Employee("Ringo"));


Console.WriteLine("\nRetrieving collections...");

Console.WriteLine("Integers: " + myLinkedList);

Console.WriteLine("Employees: " + employees);


Проверить, что списки сортируемы.