Чтение онлайн

на главную - закладки

Жанры

Интернет-журнал "Домашняя лаборатория", 2007 №9
Шрифт:

Слово делегат (delegate) используется в C# для обозначения хорошо известного понятия. Делегат задает определение функционального типа (класса) данных. Экземплярами класса являются функции. Описание делегата в языке C# представляет собой описание еще одного частного случая класса.

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

[<спецификатор доступа>] delegate <тип

результата > <имя класса> (<список аргументов>);

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

Спецификатор доступа может быть, как обычно, опущен. Где следует размещать объявление делегата? Как и у всякого класса, есть две возможности:

• непосредственно в пространстве имен, наряду с объявлениями других классов, структур, интерфейсов;

• внутри другого класса, наряду с объявлениями методов и свойств. Такое объявление рассматривается как объявление вложенного класса.

Так же, как и интерфейсы С#, делегаты не задают реализации. Фактически между некоторыми классами и делегатом заключается контракт на реализацию делегата. Классы, согласные с контрактом, должны объявить у себя статические или динамические функции, сигнатура которых совпадает с сигнатурой делегата. Если контракт выполняется, то можно создать экземпляры делегата, присвоив им в качестве значений функции, удовлетворяющие контракту. Заметьте, контракт является жестким: не допускается ситуация, при которой у делегата тип параметра — object, а у экземпляра соответствующий параметр имеет тип, согласованный с object, например, int.

Начнем примеры этой лекции с объявления трех делегатов. Поместив два из них в пространство имен, третий вложим непосредственно в создаваемый нами класс:

namespace Delegates {

//объявление классов — делегатов

delegate void Proc(ref int x);

delegate void MesToPers(string s);

class OwnDel

{

public delegate int Fun1(int x);

int Plus1(int x){return(x+100);}//Plus1

int Minus1(int x){return(x-100);}//Minus1

void Plus(ref int x){x+= 100;}

void Minus(ref int x){x-=100;}

//поля класса

public Proc p1;

public Fun1 f1;

char sign;

//конструктор

public OwnDel(char sign)

{

this.sign = sign;

if (sign == '+')

{p1 = new Proc(Plus);f1 = new Fun1(Plus1);}

else

{p1 = new Proc(Minus);f1 = new Fun1(Minus1);}

}

}//class OwnDel

Прокомментирую этот текст.

• Первым делом объявлены три функциональных класса — три делегата: Proc, MesToPers, Fun1. Каждый из них описывает множество функций фиксированной сигнатуры.

• В классе OwnDel описаны четыре метода: Plus, Minus, Plus1, Minus1, сигнатуры которых соответствуют сигнатурам, задаваемых

классами рrос и Fun1.

• Поля p1 и f1 класса OwnDel являются экземплярами классов рrос и Fun1.

• В конструкторе класса поля p1 и f1 связываются с конкретными методами Plus или Minus, Plus1 или Minus1. Связывание с той или иной функцией в данном случае определяется значением поля sign.

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

Приведу теперь процедуру, тестирующую работу созданного класса:

public void TestOwnDel

{

int account = 1000, account1=0;

OwnDel oda = new OwnDel('+');

Console.WriteLine("account = {0}, account1 = {1}",

account, account1);

oda.pl(ref account); account1=oda.f1 (account);

Console.WriteLine("account = {0}, accountl = {1}",

account, account1);

}

Клиент класса OwnDel создает экземпляр класса, передавая конструктору знак той операции, которую он хотел бы выполнить над своими счетами — account и account1. Вызов p1 и f1, связанных к моменту вызова с закрытыми методами класса, приводит к выполнению нужных функций.

В нашем примере объявление экземпляров делегатов и связывание их с внутренними методами класса происходило в самом классе. Клиенту оставалось лишь вызывать уже созданные экземпляры, но эту работу можно выполнять и на стороне клиентского класса, чем мы сейчас и займемся. Рассмотрим многократно встречавшийся класс Person, слегка изменив его определение:

class Person

{

//конструкторы

public Person{name =""; id=0; salary=0.0;}

public Person(string name){this.name = name;}

public Person (string name, int id, double salary)

{this.name = name; this.id=id; this.salary = salary;}

public Person (Person pers)

{this.name = pers.name; this.id = pers.id;

this.salary = pers.salary;}

//методы

public void ToPerson(string mes)

{

this.message = mes;

Console.WriteLine("{0}, {l}",name, message);

}

//свойства

private string name;

private int id;

private double salary;

Поделиться:
Популярные книги

Бастард Императора. Том 3

Орлов Андрей Юрьевич
3. Бастард Императора
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Бастард Императора. Том 3

Учим английский по-новому. Изучение английского языка с помощью глагольных словосочетаний

Литвинов Павел Петрович
Научно-образовательная:
учебная и научная литература
5.00
рейтинг книги
Учим английский по-новому. Изучение английского языка с помощью глагольных словосочетаний

Новые горизонты

Лисина Александра
5. Гибрид
Фантастика:
попаданцы
технофэнтези
аниме
сказочная фантастика
фэнтези
5.00
рейтинг книги
Новые горизонты

Эволюционер из трущоб. Том 7

Панарин Антон
7. Эволюционер из трущоб
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Эволюционер из трущоб. Том 7

Институт экстремальных проблем

Камских Саша
Проза:
роман
5.00
рейтинг книги
Институт экстремальных проблем

Поющие в терновнике

Маккалоу Колин
Любовные романы:
современные любовные романы
9.56
рейтинг книги
Поющие в терновнике

Отверженный VI: Эльфийский Петербург

Опсокополос Алексис
6. Отверженный
Фантастика:
городское фэнтези
альтернативная история
аниме
5.00
рейтинг книги
Отверженный VI: Эльфийский Петербург

Попаданка для Дракона, или Жена любой ценой

Герр Ольга
Любовные романы:
любовно-фантастические романы
7.17
рейтинг книги
Попаданка для Дракона, или Жена любой ценой

Царь Федор. Трилогия

Злотников Роман Валерьевич
Царь Федор
Фантастика:
альтернативная история
8.68
рейтинг книги
Царь Федор. Трилогия

Адвокат Империи 7

Карелин Сергей Витальевич
7. Адвокат империи
Фантастика:
городское фэнтези
попаданцы
альтернативная история
аниме
фантастика: прочее
5.00
рейтинг книги
Адвокат Империи 7

Инквизитор Тьмы

Шмаков Алексей Семенович
1. Инквизитор Тьмы
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Инквизитор Тьмы

Боярышня Дуняша

Меллер Юлия Викторовна
1. Боярышня
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Боярышня Дуняша

Санек

Седой Василий
1. Санек
Фантастика:
попаданцы
альтернативная история
4.00
рейтинг книги
Санек

Интриги двуликих

Чудинов Олег
Фантастика:
космическая фантастика
5.00
рейтинг книги
Интриги двуликих