Обучающие курсы:

Обучение профессии "Разработчик C#" + стажировка в Mail.ru
Обучение профессии "Разработчик Python" + трудоустройство
Обучение профессии "Веб-разработчик" + стажировка в Mail.ru


Главная страница
Библиотека (скачать книги)
Скачать софт
Введение в программирование
Стандарты для C++
Уроки по C#
Уроки по Python
HTML
Веб-дизайн
Ассемблер в среде Windows
ActiveX
Javascript
Общее о Линукс
Линукс - подробно
Линукс - новое
Delphi
Паскаль для начинающих
Турбопаскаль
Новости
Партнеры
Наши предложения
Архив новостей





Делегаты.

Делегат, какое знакомое слово .... Вспоминается СССР: “Делегаты съезда ….” В C# к счастью под понятием делегата не маскируется тот человек, которого послал народ на очередной пленум. Итак, что же это?
Делегат – это так называемый “безопасный указатель на функцию”. Однако, в отличие от обычных указателей на функцию в С++, делегаты C# могут вызывать более одной функции (при совместном комбинировании двух делегатов результатом будет делегат, который вызывает их обоих). В чем состоит “безопасность” ? В С++ указатель на функцию – это фактически просто адрес, делегат же позволяет проверять количество передаваемых параметров, возвращаемое значение и т.д..Как вы уже привыкли многие конструкции C# - это классы, так и делегат - это класс отнаследованный от базового класса System.MulticastDelegate.Делегат можно объявлять как в классе, так и просто в пространстве имен.Рассмотрим синтаксис объявления делегата:

спецификатор_доступа delegate тип_возвр_значения_для_метода Имя_Делегата(список_параметров_метода)

Небольшие комментарии к приведенному выше: 1)спецификатор_доступа - например, public и т.д. 2)delegate говорит о том что, объявляется делегат 3)тип_возвр_значения_для_метода, список_параметров_метода - определяет, на что может указывать делегат. Например:

public delegate void SetFire()

Читается это так – SetFire – это делегат на метод возвращаюший void, и не принимающий параметров.На первый взгляд всё прозрачно, однако что же мы сделали на самом деле? SetFire – это класс, который автоматически отнаследовался от System.MulticastDelegate и получил поля и методы базового класса , т.е. вот что было на самом деле:

public class SetFire:System.MulticastDelegate

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

using System;
using System.Collections;
class Human{
 // Делегат на функцию, которая ничего не возвращает и принимает объект типа h
 public delegate void HumanDelegate(Human h);
 // Перечисление 
 public enum Sex{Male,Female};
 private Sex p; 
 private string name;
 private string surname;
 private int age;
 // конструктор
 public Human(){
 	name = surname = "Нет Данных";
 	age = 0;
 	p = Sex.Male;
 }
 // конструктор с параметрами
 public Human(string name,string surname,int age,Sex p){
 	this.name = name;
 	this.surname = surname;
 	this.age = age;
 	this.p = p;
 }
 // Задание имени, возврат его
 public string Name{
	 get{
	 	return name;
	 }
	 set{
	 	name = value;
	 }
 }
 // Задание фамилии, возврат её
 public string Surname{
	 get{
	 	return name;
	 }
	 set{
	    name = value;
	 }
 }
 // Задание возраста, возврат его
 public int Age{
	 get{
	 	return age;
	 }
	 set{
	 	age = value;
	 }
 }
 // Задание пола,возврат его
 public Sex RealSex{
	 get{
	 	return p;
	 }
	 set{
	 	p = value;
	 }
 }
 
}
//Класс, содержащий людей
class Firm{
	ArrayList people = new ArrayList();
	public Firm(){
		// Добавляем в список 3 - х людей
		people.Add(new Human());
		people.Add(new Human("Вася","Иванов",80,Human.Sex.Male));
		people.Add(new Human("Катерина","Маркова",25,Human.Sex.Female));

	}
	// Метод, принимающий делегат, четко указывается  название класса, 
	//где содержится делегат, а также название делегата
	public void AnalyzePeople(Human.HumanDelegate ptr){
		Console.WriteLine("Будем выполнять действия над человеком !!!");
		// Вызываются методы, на которые указывает делегат
		foreach(Human obj in people)
			ptr(obj);
	}
}

class Sample
{
	// Проверка пола	
	static void AnalyzeSex(Human h){
		if(h.RealSex==Human.Sex.Male){
			Console.WriteLine("Мужчина");
		}
		else{
			Console.WriteLine("Женщина");

		}
	}
	// Проверка по возрасту
	static void AnalyzeAge(Human h){
		if(h.Age>65){
			Console.WriteLine("Больше 65 лет");
		}
		else{
			Console.WriteLine("Меньше или равно 65 лет");

		}
	}

	static void Main() 
	{
		Console.WriteLine("Пример работы Делегата");
		Firm firm = new Firm();
		// В этой строке происходит использование делегатов. Создаётся объект 				// делегата используя 
		// ключевое слово new.
		// Сейчас делегат указывает на метод AnalyzeSex
		firm.AnalyzePeople(new Human.HumanDelegate(AnalyzeSex));
		// Сейчас делегат указывает на метод AnalyzeAge
		firm.AnalyzePeople(new Human.HumanDelegate(AnalyzeAge));
		Console.Read();
	}
}

Вывод:

Пример работы Делегата
Будем выполнять действия над человеком !!!
Мужчина
Мужчина
Женщина
Будем выполнять действия над человеком !!!
Меньше или равно 65 лет
Больше 65 лет
Меньше или равно 65 лет

Обратите внимание на то, что у нас сейчас делегат, вложенный в класс и поэтому для доступа к нему мы используем имя класса:

firm.AnalyzePeople(new Human.HumanDelegate(AnalyzeAge));

Как уже было сказано выше делегат это класс отнаследованный от System.MulticastDelegate. Рассмотрим 2 полезных метода этого базового класса. Первый метод Combine – этот статический метод используется для создания делегата, указывающего на несколько разных функций (также можно пользоваться перегруженным оператором +), второй Remove - этот статический метод удаляет делегат из списка указателей на функции. Если делегат указывает на несколько методов, то тогда при вызове делегата будут вызываться методы,на которые указывает делегат. Например(те же самые классы другой Main):

static void Main(){
		Console.WriteLine("Пример работы Делегата");
		Firm firm = new Firm();
		// Создание делегатов
		Human.HumanDelegate sex = new Human.HumanDelegate(AnalyzeSex);
		Human.HumanDelegate age = new Human.HumanDelegate(AnalyzeAge);

		// Многоадресный Делегат (формируем его через +)
		// Произойдет вызов методов AnalyzeSex и AnalyzeAge
		firm.AnalyzePeople(sex+age);
		Console.WriteLine("\n\n");
		// Многоадресный Делегат (формируем его через +)
		// Произойдет вызов методов AnalyzeSex и AnalyzeAge
		firm.AnalyzePeople(age+sex);
		
		// Или так тоже Многоадресный Делегат
		Console.WriteLine("\n\n");
		// Многоадресный Делегат (формируем его через Combine)
		// Произойдет вызов методов AnalyzeSex и AnalyzeAge
		firm.AnalyzePeople((Human.HumanDelegate)Delegate.Combine(sex,age));
		// Или так тоже можно
		MulticastDelegate del = age+sex;
		firm.AnalyzePeople((Human.HumanDelegate)del);
		// Удаляем один делегат
		Delegate onlysex = MulticastDelegate.Remove(del,age);
		Console.WriteLine("\n\n************************************\n\n");
		// Уже не многоадресный делегат
		firm.AnalyzePeople((Human.HumanDelegate)onlysex);

		Console.Read();
}

Сейчас мы через делегат вызывали статические методы класса, но это можно делать и с обычными. Для этого надо чуть-чуть видоизменить создание делегата. Например:

Firm firm = new Firm();
// Test - это какой-то класс в нем есть методы AnalyzeSex,
// AnalyzeAge 
Test test = new Test();
//
firm.AnalyzePeople(new Human.HumanDelegate(test.AnalyzeSex));
firm.AnalyzePeople(new Human.HumanDelegate(test.AnalyzeAge));


 
 
 

Библиотека программиста. 2009.
Администратор: admin@programmer-lib.ru