C#. Частина 3. Делегати. Групова адресація. Створення ланцюгів викликів методів




Частина 3. Делегати. Групова адресація. Створення списків викликів методів

Дана тема базується на попередній темі:


Зміст


Пошук на інших ресурсах:

1. Що означає термін “групова адресація методів”?

Делегат може посилатись на групу методів, які зв’язані між собою в зв’язаний однонаправлений список (ланцюг). Групова адресація – це спосіб (можливість) створення списку методів, які викликаються автоматично при зверненні до делегату.

 

2. Які переваги дає використання групової адресації при роботі з делегатами?

Групова адресація дозволяє сформувати списки (ланцюги) викликів. Це є ефективним, оскільки:

  • можна гнучко формувати списки методів, що повинні викликатись одним єдиним викликом делегату;
  • зручно формувати списки методів, які виконують різні види роботи над деяким спільним об’єктом;
  • покращується структура програмного коду;
  • зручно обробляти події, які генеруються системою.

 

3. Які операції використовуються при груповій адресації?

Для організації групової адресації методів з допомогою делегата використовуються 4 операції:

  • операції ‘+’ та ‘+=’ – додають метод до списку методів;
  • операції ‘−’ та ‘−= – видаляють метод зі списку методів.

 

4. Приклад додавання та видалення методів списку

Нехай дано методи з іменами Method1(), Method2(), Method3(). Нехай задано делегат з іменем ListM.

Нижченаведений код демонструє використання операцій ‘+’, ‘+=’, ‘–’, ‘−=’.

Щоб додати метод Method2 до делегату (списку) ListM, потрібно виконати такий код:

ListM = ListM + Method2;

Інший спосіб додавання методу

ListM += Method2;

Щоб видалити метод Method2 потрібно написати:

ListM = ListM - Method2;

або

ListM -= Method2;

 

5. Що відбудеться, якщо видалити метод, якого немає в списку методів?

Нічого не відбудеться. Якщо методу з іменем M немає в списку (ланцюгу) методів, тоді рядок видалення (операції ‘−’ або ‘−=’) пропускається.

 

6. Як здійснюється групова адресація, якщо делегат повертає значення?

Якщо в делегаті сформований список методів, які повертають деякий тип, відмінний від типу void, тоді результатом виклику буде результат повернення останнього методу в списку.

Щоб отримати результат роботи всіх методів списку, потрібно використати метод GetInvocationList(). Цей метод повертає масив усіх методів, що сформовані в делегаті у вигляді списку.

 

7. Як працює групова адресація, якщо делегат повертає тип void?

Якщо делегат повертає тип void, то при виклику делегата викликаються усі методи, що сформовані в список (ланцюг) з допомогою групової адресації.

Послідовність виклику методів відповідає послідовності додавання методів до списку. Перший доданий метод викликається першим, другий доданий метод викликається другим і т.д.

 



8. Приклад, що демонструє використання групової адресації для делегатів, які повертають значення (методи повертають значення)

Приклад, в якому делегат повертає значення. Для демонстрації вибрано методи обчислення характеристик геометричних фігур (довжина кола, площа круга, об’єм сфери).

Приклад.

Дано оголошення типу делегату CalcFigures, який повертає значення типу double:

// Оголошення типу делегату, що повертає значення
delegate double CalcFigures(double r);

Дано опис статичних методів, що будуть формуватись в список:

// Оголошення статичних методів класу
// довжина кола
public static double Get_Lentgh(double r)
{
    double length = 3.1415 * r * 2;
    return length;
}

// площа круга
public static double Get_Area(double r)
{
    double area = 3.1415 * r * r;
    return area;
}

// об'єм кулі
public static double Get_Volume(double r)
{
    double volume = 4.0 / 3.0 * 3.1415 * r * r * r;
    return volume;
}

В іншому програмному коді (наприклад, обробнику події) оголошуються делегати та формується список (група) методів, на які посилається делегат:

// Оголошення делегатів
CalcFigures CF;
CalcFigures GetL = Get_Lentgh;
CalcFigures GetA = Get_Area;
CalcFigures GetV = Get_Volume;

...

// організувати групову адресацію
CF = GetL; // CF посилається на метод Get_Length: CF->GetL

// додати до списку CF метод Get_Volume
CF = CF + GetV; // або CF += GetV;

// додати до списку CF метод Get_Area
CF += GetA; // CF => Get_Length->Get_Volume->Get_Area
result = CF(3.0); // result = 28.2735 - викликається метод Get_Area

// видалити зі списку CF метод Get_Area
CF -= GetA; // CF => Get_Length->Get_Volume
result = CF(3.0); // result = 113.094 - викликаєтья метод Get_Volume

// додати знову метод Get_Length
CF += GetL; // CF => Get_Length->Get_Volume->Get_Length
result = CF(3.0); // result = 18.849 - викликається Get_Length

// видалити метод Get_Length
CF -= GetL; // CF => Get_Length->Get_Volume

result = CF(3.0); // result = 113.094 - викликається Get_Volume

// видалити знову Get_Length
CF -= GetL; // CF => Get_Volume - у списку залишився один метод Get_Volume
result = CF(3.0); // result = 113.094

// видалити останній метод Get_Volume
CF -= GetV; // CF => список пустий

 

9. Приклад, що демонструє використання групової адресації для делегатів, які повертають тип void

У даному прикладі продемонстровано групову адресацію для методів, що здійснюють деяку операцію над дійсним числом x, а саме:

  • множення числа x на 2 (метод Mult2());
  • множення числа x на 3 (метод Mult3());
  • піднесення числа x до квадрату (метод Sqr()).

Оголошення типу делегату:

// Оголошення типу делегату
delegate void CalcNumber(ref double x);

Оголошення методів

// методи, що обробляють дійсне число
// множення числа на 2
public static void Mult2(ref double x)
{
    x = x * 2;
}

// множення числа на 3
public static void Mult3(ref double x)
{
    x = x * 3;
}

// піднесення числа до квадрату
public static void Sqr(ref double x)
{
    x = x * x;
}

Демонстрація групової адресації для делегату що повертає тип void, з іншого програмного коду (наприклад, обробника події):

// Оголошення делегату
CalcNumber CN;

// додаткова змінна
double x;

// Створення списку методів - 1
CN = Mult2; // CN => Mult2
CN += Mult2; // CN => Mult2 -> Mult2
CN += Sqr; // CN => Mult2 -> Mult2 -> Sqr
CN = CN + Mult3; // CN => Mult2 -> Mult2 -> Sqr -> Mult3

x = 2.0;
CN(ref x); // x = 192 = ((2.0 * 2 * 2)^2 ) * 3

// Видалення усіх методів
CN -= Mult3;
CN -= Mult2;
CN -= Mult2;
CN -= Sqr; // CN => список пустий

// Створення списку методів - 2
CN = Sqr; // CN => Sqr
CN += Sqr; // CN => Sqr -> Sqr
CN += Mult3; // CN => Sqr -> Sqr -> Mult3
CN += Mult2; // CN => Sqr -> Sqr -> Mult3 -> Mult2

x = 2.0;
CN(ref x); // x = 96 = (2.0 ^ 2 ^ 2) * 3 * 2

 


Зв’язані теми