Опубликован: 11.09.2006 | Уровень: специалист | Доступ: свободно
Лекция 1:

Введение в windows-формы

Лекция 1: 12345678910 || Лекция 2 >

Многообъектные делегаты

В коде Matem2 делегат Mydelegate и метод calculate имеют одинаковую сигнатуру в соответствии с общими правилами. Для обращения через делегат к методу используется переменная int chislo, не содержащая вводимых значений для вычислений. Мы использовали один экземпляр делегата для обращения к одному методу, причем для вычисления значения новой переменной мы каждый раз ее объявляли. Однако делегат может вмещать в себя несколько методов. Такой делегат называется многообъектным (множественным) — при обращении к нему он последовательно вызывает каждый метод.

Создайте новое консольное приложение. Назовите его Matem3. Рассмотрим листинг с комментариями этого приложения (результат — рис. 1.35):

using System;

namespace Matem3
{
		class matematika
	{
		
		public int a;

		public void calculatesamochislo(int chislo)
		{
			Console.WriteLine ("Само число: " + a);
		}
		public void calculatecvadrat(int chislo)
		{
			int b = a*a;
			Console.WriteLine ("\nКвадрат: " + b);
		}
		public void calculatecub(int chislo)
		{
			int c = a*a*a;
			Console.WriteLine ("\nКуб: " + c);
		}
	}

	class Class1
	{
		delegate void Mydelegate(int chislo);
		
		[STAThread]
		static void Main(string[] args)
		{
			matematika primer = new matematika();
			Mydelegate del = new Mydelegate(primer.calculatesamochislo);
			//Экземпляру делегата del добавляем метод calculatecvadrat
			del+= new Mydelegate(primer.calculatecvadrat);
			//Экземпляру делегата del добавляем метод calculatecub
			del+= new Mydelegate(primer.calculatecub);
			primer.a = 2;
			del(1);
//		//Развернутый вариант
//			del=del + new Mydelegate(primer.calculatecvadrat);
//			del = del+ new Mydelegate(primer.calculatecub);
//			primer.a = 2;
//			del(1);

		}
	}
}
Листинг 1.5.

В языке С# вы уже сталкивались с сокращенной записью операторов, так, выражение x += y в развернутом виде означает x = x + y. Делегаты понимают синтаксис + и +=, и поэтому в комментарии указывается развернутый вариант добавления методов. Делегаты понимают также операции – и –= для удаления вызовов методов из делегата.

Результат приложения Matem3

Рис. 1.35. Результат приложения Matem3

События

С помощью событий приложения Windows получают уведомления о том, что что-то произошло. Например, при нажатии на кнопку мыши приложение, в окне которого вы произвели это действие, будет уведомлено об этом событии. То же самое происходит, когда вы делаете что-то с помощью клавиатуры. Событийная модель стала основой современного программирования. Обработчик события реализуется на языке С#, как правило, в виде делегата.

Создайте новое консольное приложение и назовите его Event (Событие). Рассмотрим листинг этого приложения:

using System;

namespace Event
{
	//Объявляем делегат Mydelegate
	delegate void Mydelegate();
	//Создаем класс Button, в котором будет находится событие и метод  для него
	class Button
	{
		// Объявляем событие Sobitie на основе делегата
		public event Mydelegate Sobitie;
		//Cоздаем метод для события, который просто будет обращаться к событию
		public void MetoddlyaSobitiya()

		{
			//Можно вставить проверку наличия события 
		//if (Sobitie !=null)
			Sobitie();
		}


		class Class1
		{
			[STAThread]
			static void Main(string[] args)
			{
				// Создаем экземпляр btn класса Button
				Button btn = new Button();
				//привязываем обработчика  для события Sobitie экземпляра btn. Когда в //скобках укажете 
				// Metodobrabotchik, нажмите дважды клавишу Tab
				btn.Sobitie += new Mydelegate(Metodobrabotchik);
				//Развернутая запись строки выше
				//btn.Sobitie =  btn.Sobitie + new Mydelegate(Metodobrabotchik);
				//вызываем метод для события
				btn.MetoddlyaSobitiya();
			}
				// Создаем метод-обработчик, если среда сгенерировала его сама — добавляем //строку вывода
				private static void Metodobrabotchik ()
				{
						Console.WriteLine("Произошло событие");
				}
			}
		}
	}
Листинг 1.6.

Сначала мы в строке

delegate void Mydelegate();

объявляем делегат. Параметров у него нет (хотя могут и быть), тип — void.

Затем мы объявляем класс Button, внутри которого объявляем событие Sobitie (имя произвольное):

...
    public event Mydelegate Sobitie;
    ...

Синтаксис следующий: модификатор доступа (здесь — public), затем ключевое слово event, потом имя делегата, на основании которого мы создаем наше событие (здесь Mydelegate) и, наконец, имя события (Sobitie). Обратите внимание, что событие появится на вкладке Class View (рис. 1.36).

Событие в окне Class View. Значок события имеет характерный вид молнии

Рис. 1.36. Событие в окне Class View. Значок события имеет характерный вид молнии

Далее в нашем классе с событиями мы в некотором методе это событие вызываем:

...
public void MetoddlyaSobitiya()

		{
			Sobitie();
		}

Класс с событием создан. Далее в классе Class1 мы объявляем экземпляр btn нашего класса Button (того самого, в котором мы объявили событие):

Button btn = new Button();

Остается теперь указать, что за обработчик будет у события Sobitie класса Button. Это мы делаем в строке

btn.Sobitie += new Mydelegate(Metodobrabotchik);

Этой строчкой мы указываем, что событие Sobitie будет обрабатывать метод Metodobrabotchik класса Class1. Когда мы указываем этот метод, IntellSense предложит дважды нажать клавишу Tab для создания шаблона метода Metodobrabotchik. Сделав это, нам останется только добавить код в методе — здесь вывод строки "Произошло событие":

…

private static void Metodobrabotchik ()
{
		Console.WriteLine("Произошло событие");
}

…

Результатом выполнения этой программы станет вывод на экран строки "Произошло событие" (рис. 1.37).

Результат приложение Event

Рис. 1.37. Результат приложение Event

Для того чтобы лучше разобраться в логике этого листинга, желательно просмотреть ее выполнение в пошаговом режиме (используйте клавишу F11).

Класс с событием

Даже в консольных приложениях использование делегатов и событий — необходимый и удобный способ реализации многих идей. Рассмотрим приложение, имитирующее выпадение игральной кости. Если выпадет число 6, сгенерируется событие — max. Создайте новое консольное приложение, назовите его ClasswithEvent и воспользуйтесь следующим кодом:

using System;

namespace ClasswitnEvent
{
	//Объявляем делегат по имени EventHandler (Event Handler — oбработчик события)
	public delegate void EventHandler();
	// Создаем класс "Игральная кость"
	class IgralnayaKost
	{
		Random r;
		//Объявляем событие на основе делегата
		public event EventHandler max;
		//В конструкторе класса объявляем переменную r, генерируемую встроеным объектом Random
		public IgralnayaKost()
		{
			r=new Random();
		}
		//Создаем метод, в котором будет вызываться событие
		public int random()
		{
			//Случайное число от 1 до 6
			int res = r.Next(6)+1;
			if(res==6)
			{
				//Вызываем событие
				max();
			}
			return res;
		}
	}


	class Class1
	{
		/// <summary>
		/// The main entry point for the application
		/// </summary>
		[STAThread]
		static void Main(string[] args)
		{		
		
			//Создаем экземпляр brosok класса IgralnayaKost
			IgralnayaKost brosok=new IgralnayaKost();
			//Добавляем  обработчика события
			brosok.max+=new EventHandler(Metodobrabotchik);
			//Вызываем  метод, в котором вызывается событие
			for(int i=0; i<15; i++)
			{
				Console.WriteLine("{0}", brosok.random());
			}

		}
		//Обработчик для события
		public static void Metodobrabotchik()
		{
			Console.WriteLine("Выпало максимальное количество очков");
		}
	}
}
Листинг 1.7.

В классе Class1 создается новый экземпляр brosok класса IgralnayaKost, затем событию max определяется обработчик Metodobrabotchik и запускается метод random 15 раз. Если выпадет шестерка, то возникнет событие max и сработает обработчик для него. Результат выполнения программы будет каждый раз разный и будет выглядеть примерно так (рис. 1.38):

Результат приложения ClasswithEvent

Рис. 1.38. Результат приложения ClasswithEvent
Лекция 1: 12345678910 || Лекция 2 >
Елена Дьяконова
Елена Дьяконова

При нажатии на Сумма в примере ArbitraryMethod из Лекция 7, VS 2013 выдается ошибка: 

Необработанное исключение типа "System.InvalidOperationException" в System.Windows.Forms.dll

Дополнительные сведения: Недопустимая операция в нескольких потоках: попытка доступа к элементу управления "lblResult" не из того потока, в котором он был создан.

Затем:

Необработанное исключение типа "System.InvalidOperationException" в mscorlib.dll

Дополнительные сведения: Для каждой асинхронной операции метод EndInvoke может вызываться только один раз.

Александр Сороколет
Александр Сороколет

Свойство WindowState формы blank Maximized. Не открывается почемуто на всё окно, а вот если последующую форму бланк открыть уже на макс открывается :-/