- •Общие требования
- •1 Примеры реализации заданий
- •1.1 Основные элементы класса
- •1.2 Перегрузка операторов
- •1.3 Использование делегатов
- •1.4 Универсальные типы библиотеки .Net Framework
- •2 Варианты заданий
- •2.1 Основные элементы класса
- •2.2 Перегрузка операторов
- •2.3 Использование делегатов
- •2.4 Универсальные типы библиотеки .Net Framework
Result_TB.Text = "\"" + Spisok_LB.SelectedItem + "\" > \"" + E + "\" = " + Result;
}
else
MessageBox.Show("Не выбран элемент", "Ошибка");
}
Внешний вид и пример работы программы показаны на рисунке 21.
Рисунок 2 – Внешний вид и пример работы программы, реализующей перегрузку операторов
1.3 Использование делегатов
Задание2: создать класс с заданными параметрами и реализовать работу с ним.
Описание параметров задания
1Здесь и далее для получения внешнего вида приложения, аналогичного показанному на рисунке, требуется настройка ряда свойств основной формы
2Полные требования к выполнению задания приведены в общей части раздела
2.3
20
делегаты:
1.делегат для обратного вызова, позволяющий вывести описание выполненного действия;
2.делегат, позволяющий выполнить набор действий с элементом списка. Параметрами делегата является целое число, а также делегат типа
«1»;
обязательные поля класса:
1.идентификатор, int, уникальный;
2.первое число, int;
3.второе число, int, ≠0, по умолчанию 1;
4.ссылка на компонент, в котором хранится и отображается элемент;
отображение: «<идентификатор> : <первое число>/<второе число>»;
обязательные методы класса:
1.метод, добавляющий к первому числу переданное значение и вызывающий делегат типа «1» для передачи описания выполненного действия;
2.метод, добавляющий ко второму числу переданное значение и вызывающий делегат типа «1» для передачи описания выполненного действия;
операции, требующие реализации:
1.добавление к первому числу;
2.добавление ко второму числу;
3.удаление добавления к первому числу;
4.удаление добавления ко второму числу;
5.удаление всех операций.
Примечание: при отображении информации о классе вместо данных в угловых скобках подставляются значения полей
Для решения поставленной задачи потребуются компоненты:
Spisok_L класса Label для подписи компонента Spisok_LB;
Spisok_CLB класса CheckedListBox для хранения списка элементов;
AddElement_GB класса GroupBox для визуального выделения компонентов добавления элемента списка;
First_L класса Label для подписи компонента First_TB;
First_TB класса TextBox для ввода первого числа элемента
списка;
Second_L класса Label для подписи компонента Second_TB;
Second_TB класса TextBox для ввода второго числа элемента
списка;
21
AddElement_B класса Button для активизации добавления элемента списка;
DelElement_B класса Button для активизации удаления помеченных элементов списка;
Opeartions_GB класса GroupBox для визуального выделения компонентов назначения операций элементам списка;
AddFirst_B класса Button для активизации назначения помеченным элементам списка операции «Добавление к первому числу»;
AddSecond_B класса Button для активизации назначения помеченным элементам списка операции «Добавление ко второму числу»;
DelFirst_B класса Button для активизации назначения помеченным элементам списка операции «Удалить добавление к первому числу»;
DelSecond_B класса Button для активизации назначения помеченным элементам списка операции «Удалить добавление ко второму числу»;
Clear_B класса Button для активизации назначения помеченным элементам списка операции «Удалить все операции»;
Run_GB класса GroupBox для визуального выделения компонентов выполнения назначенных операций;
Number_L класса Label для подписи компонента Number_TB;
Number_TB класса TextBox для ввода числа, которое будет передано в качестве параметра при выполнении назначенных операций;
Calc_B класса Button для активизации выполнения назначенных операций;
Result_L класса Label для подписи компонента Result_TB;
Result_TB класса TextBox для вывода списка выполненных операций, полученных за счет делегата обратного вызова.
Установим следующие значения свойств компонентов (таблица 4).
Таблица 4 – Значения свойств компонентов для примера выполнения задания по использованию делегатов
Компонент.Свойство |
Значение |
|
|
Spisok_L.Text |
Спи&сок элементов |
AddElement_GB.Text |
Добавление нового элемента |
First_L.Text |
П&ервое число добавляемого элемента |
Second_L.Text |
В&торое число добавляемого элемента |
AddElement_B.Text |
До&бавить элемент |
DelElement_B.Text |
У&далить все помеченные элементы |
Opeartions_GB.Text |
Назначение операций помеченным объектам |
AddFirst_B.Text |
Добавление к &первому числу |
22
AddSecond_B.Text |
Добавление ко &второму числу |
DelFirst_B.Text |
Удалить добавление к &первому числу |
DelSecond_B.Text |
Удалить добавление ко второму &числу |
Clear_B.Text |
Уд&алить все операции |
Run_GB.Text |
Выполнение операций |
Number_L.Text |
Число для операци&й |
Calc_B.Text |
В&ыполнить действие |
Result_L.Text |
Выполненные &операции |
Result_TB.Multiline |
True |
|
|
Result_TB.ReadOnly |
True |
|
|
Для реализации класса (назовём его Element) потребуется отдельный модуль. Добавим его в программу через меню «Проект → Добавить класс». Также в этом модуле опишем требуемые делегаты. Реализация делегатов и членов класса приведена ниже.
//Делегат обратного вызова, в качестве параметра которого
//передается выводимая строка
public delegate void CalcBack(string s);
//Делегат, позволяющий вызвать методы класса и возвратить
//после выполнения метода требуемую строку
public delegate void CalcDelegate(int n,
CalcBack PrintResult);
class Element
{
private static int _Count; // Счетчик объектов private int _ID, _First, _Second;
//Ссылка на компонент отображения private CheckedListBox _LB;
//Конструкторы
public Element() : this(1, 1, null) { }
public Element(int First, int Second, CheckedListBox LB)
{
_ID = ++_Count; _First = First;
_Second = Second != 0 ? Second : 1; _LB = LB;
}
// Свойства для работы с полями public int First
{
get { return _First; } set
{
_First = value;
23
// Изменение отображения объекта в компоненте if (_LB != null)
_LB.Items[_LB.Items.IndexOf(this)] = this;
}
}
public int Second
{
get { return _Second; } set
{
if (value != 0)
{
_Second = value;
// Изменение отображения объекта в компоненте if (_LB != null)
_LB.Items[_LB.Items.IndexOf(this)] = this;
}
}
}
//Переопределение метода отображения объекта public override string ToString()
{
return _ID + " : " + First + "/" + _Second;
}
//Первый обязательный метод
public void AddFirst(int n, CalcBack PrintResult)
{
//Выполнение операции
_First += n;
//Изменение отображения объекта в компоненте
if (_LB != null) _LB.Items[_LB.Items.IndexOf(this)] = this;
// Вызов делегата для возврата требуемой строки
PrintResult(string.Format(
"Объект №{0}. Добавлено {1} к первому числу", _ID, n));
}
// Второй обязательный метод
public void AddSecond(int n, CalcBack PrintResult)
{
_Second = _Second + n != 0 ? _Second + n : 1; if (_LB != null)
_LB.Items[_LB.Items.IndexOf(this)] = this; PrintResult(string.Format(
"Объект №{0}. Добавлено {1} ко второму числу", _ID, n));
}
}
24
В классе основной формы опишем поле типа CalcDelegate, которое будет хранить список операций, которые необходимо выполнять:
public CalcDelegate Calc = null;
Опишем событие Click кнопки AddElement_B:
private void AddElement_B_Click(object sender, EventArgs e)
{
int c = 0; try
{
int First = Convert.ToInt32(First_TB.Text); c = 1;
int Second = Convert.ToInt32(Second_TB.Text); if (Second == 0)
{
Second_TB.Focus(); throw new Exception(
"Второе число не должно равняться нулю");
}
Spisok_CLB.Items.Add(new Element(First, Second, Spisok_CLB));
}
catch (FormatException)
{
if (c == 0)
{
First_TB.Focus();
MessageBox.Show("Первое число должно быть целым числом", "Требуется исправление");
}
else
{
Second_TB.Focus();
MessageBox.Show("Второе число должно быть целым числом", "Требуется исправление");
}
}
catch (Exception E)
{
MessageBox.Show(E.Message, "Требуется исправление");
}
}
Опишем событие Click кнопки DelElement_B:
private void DelElement_B_Click(object sender, EventArgs e)
{
//Так как при удалении элемента происходит сдвижка всех
//последующих элементов к началу списка, проще осуществлять
25
// перебор элементов с конца списка
for (int i = Spisok_CLB.Items.Count - 1; i >= 0; i--)
// Проверка, помечен ли текущий элемент if (Spisok_CLB.GetItemChecked(i))
Spisok_CLB.Items.RemoveAt(i);
}
Опишем событие Click кнопки AddFirst_B:
private void AddFirst_B_Click(object sender, EventArgs e)
{
for (int i = 0; i < Spisok_CLB.Items.Count; i++) if (Spisok_CLB.GetItemChecked(i))
{
// Получение помеченного элемента
Element Item = Spisok_CLB.Items[i] as Element;
//Добавление в поле типа «делегат» ссылки на метод
//помеченного элемента
Calc += Item.AddFirst;
}
}
Опишем событие Click кнопки AddSecond_B:
private void AddSecond_B_Click(object sender, EventArgs e)
{
for (int i = 0; i < Spisok_CLB.Items.Count; i++) if (Spisok_CLB.GetItemChecked(i))
{
Element Item = Spisok_CLB.Items[i] as Element; Calc += Item.AddSecond;
}
}
Опишем событие Click кнопки DelFirst_B:
private void DelFirst_B_Click(object sender, EventArgs e)
{
if (Calc != null)
for (int i = 0; i < Spisok_CLB.Items.Count; i++) if (Spisok_CLB.GetItemChecked(i))
{
Element Item = Spisok_CLB.Items[i] as Element; int n;
//Так как метод может быть добавлен в поле типа
//«делегат» несколько раз, то производим его удаление
//до тех пор, пока после выполнения операции удаления
//количество добавленных в поле методов не останется
//таким же, как и до удаления
do
{
26
//Запрос текущего количества методов, добавленных в
//поле типа «делегат»
n = Calc.GetInvocationList().Length; Calc -= Item.AddFirst;
}
while (n != Calc.GetInvocationList().Length);
}
}
Опишем событие Click кнопки DelSecond_B:
private void DelSecond_B_Click(object sender, EventArgs e)
{
if (Calc != null)
for (int i = 0; i < Spisok_CLB.Items.Count; i++) if (Spisok_CLB.GetItemChecked(i))
{
Element Item = Spisok_CLB.Items[i] as Element; int n;
do
{
n = Calc.GetInvocationList().Length; Calc -= Item.AddSecond;
}
while (n != Calc.GetInvocationList().Length);
}
}
Опишем событие Click кнопки Clear_B:
private void Clear_B_Click(object sender, EventArgs e)
{
Calc = null;
}
При выполнении назначенных операций требуется, в соответствии с заданием, передача в метод делегата обратного вызова. Опишем метод, соответствующий сигнатуре делегата обратного вызова, который будет выводить описание выполненной операции в компонент отображения:
private void PrintResult(string s)
{
Result_TB.AppendText(s + Environment.NewLine);
}
Опишем событие Click кнопки Calc_B:
private void Calc_B_Click(object sender, EventArgs e)
{
try
27
{
int Number = Convert.ToInt32(Number_TB.Text); Result_TB.Clear();
//Если операции назначены, то выполняем их if (Calc != null)
Calc(Number, PrintResult); else
//Иначе выводим сообщение
PrintResult("Не назначено ни одной операции");
}
catch (FormatException)
{
Number_TB.Focus();
MessageBox.Show("Число для операции должно быть целым", "Требуется исправление");
}
}
Внешний вид и пример работы программы показаны на рисунке .
Рисунок 3 – Внешний вид и пример работы программы, реализующей использование делегатов
28