Делегати. Частина 4. Анонімні функції. Анонімні методи. Повернення значення. Передача параметрів

Делегати. Частина 4. Анонімні функції. Анонімні методи. Повернення значення. Передача параметрів


Зміст



1. Що називається анонімною функцією?

Анонімна функція – це функція, яка не має імені а містить тільки блок програмного коду, який вона виконує.
Анонімні функції зручно використовувати у поєднанні з делегатами. Анонімну функцію можна викликати тільки з допомогою делегату. Сама функція безпосередньо не викликається ніколи.

 

2. Які є види анонімних функцій?

У мові програмування C# передбачено 2 види анонімних функцій:

 

3. У яких випадках доцільно використовувати анонімні функції у програмах на C#?

Часто буває так, що делегат посилається тільки на один метод і більше ні на який інший. Сам же метод безпосередньо не викликається. У цьому випадку ім’я методу можна не використовувати, а описати тільки блок програмного коду методу. Мова програмування C# передбачає оголошення кодового блоку методу, який буде передаватись конструктору делегату. Тобто, оголошується безіменний блок програмного коду.

 

4. Переваги використання анонімних функцій

Використання анонімних функцій дає такі переваги:

  • простота використання;
  • відсутність оголошення окремого методу, призначеного строго для передачі його делегату.

 

5. Яка загальна форма оголошення анонімного методу, який не повертає значення і не отримує параметрів?

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

delegate 
{
    // Програмний код методу
    // ...
}

 

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

Завдання

Нехай дано додаток, створений за шаблоном Windows Forms Application – C#. У цьому додатку головній формі відповідає клас Form1, який має такий вигляд:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace TrainDelegates04
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
    }
}

Продемонструвати виклик методу, який не отримує і не повертає значення. Метод виводить на форму текст привітання “Hello world!!!”.

Виконання

1. Оголосити тип делегату

// оголошення типу делегату, який не отримує і не повертає значення
delegate void HELLO();

2. Розмістити на формі елемент управління типу Button. У результаті буде створено об’єкт з іменем button1.

3. Запрограмувати обробник події кліку на кнопці button1. В обробнику події набрати такий програмний код

// Вивід тексту 'Hello world!!!' через делегат
// Делегат має ім'я HW, метод - анонімний
HELLO HW = delegate
{
 // програмний код методу
 label1.Text = "Hello world!";
};

// виклик анонімного методу з допомогою делегату
HW();

Загальний програмний код модуля “Form1.cs”, що описує клас форми Form1:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace TrainDelegates04
{
    public partial class Form1 : Form
    {
        // оголошення типу делегату, який не отримує і не повертає значення
        delegate void HELLO();

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            // Вивід тексту 'Hello world!!!' через делегат
            // Делегат має ім'я HW, метод - анонімний
            HELLO HW = delegate
            {
                // програмний код методу
                label1.Text = "Hello world!";
            };

            // виклик анонімного методу з допомогою делегату
            HW();
        }
    }
}

 

7. Як анонімному методу передати аргументи (параметри)?

Загальна форма анонімного методу, який отримує параметр і не повертає значення

Якщо анонімному методу потрібно передати один або декілька параметрів, то загальна форма оголошення такого делегату має вигляд:

delegate (список_параметрів)
{
    // Програмний код методу
    // ...
}

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

 

8. Як реалізувати повернення значення з анонімного методу?

Повернення значення з анонімного методу здійснюється так само як і у випадку зі звичайним методом. Для повернення значення використовується ключове слово return. Загальний вигляд анонімного методу, який отримує вхідні параметри і повертає значення наступний:

delegate (список_параметрів)
{
    // Програмний код методу
    // ...
    return величина;
}

де величина – змінна або вираз або значення, що повертається.

 

9. Приклад виклику анонімного методу, що повертає значення і отримує параметри

Завдання

Реалізувати функцію, що знаходить площу трикутника за формулою Герона. Функція отримує вхідним параметром значення трьох сторін трикутника a, b, c.

Якщо введено некоректні значення a, b, c, то функція повертає -1 (від’ємне число).

Виконання

Оголосити тип делегата у тілі класу (наприклад, класу форми Form1 для додатків типу Windows Forms Application).

// Оголошення типу делегату
delegate float SquareTriangle(float a, float b, float c);

Реалізувати в іншому програмному коді (наприклад, обробнику події) метод обчислення площі трикутника за формулою Герона.

// Оголошення делегату з іменем ST, що обчислює площу трикутника
SquareTriangle ST;
ST = delegate(float a, float b, float c)
{
    float s, p, d;

    p = (a + b + c)/2.0f;
    d = p*(p-a)*(p-b)*(p-c);
    if (d<0) return -1.0f;
    s = (float)Math.Sqrt(p*(p-a)*(p-b)*(p-c));

    return (float)s;
};

// Виклик делегату
float area;
area = ST(2.0f, 3.0f, 2.2f); // area = 2.199636
area = ST(3.0f, 4.0f, 5.0f); // area = 6.0
area = ST(1.0f, 5.0f, 7.0f); // area = -1.0 - невірні вхідні дані

Більш детально даний приклад розписаний в статті:

 

10. Які особливості застосування зовнішніх змінних в анонімних методах?

В анонімних методах можна використовувати зовнішні змінні. Зовнішні змінні для анонімних методів – це локальні змінні методу, з якого викликається анонімний метод.

Приклад.

Нехай в деякому класі оголошено зовнішню змінну a та тип делегату CalcA:

// зовнішня змінна a
private int a;

// тип делегату CalcA 
delegate void CalcA();

Фрагмент коду, що демонструє використання змінної a у обробнику події або іншому методі цього ж класу:

// Оголошення анонімного методу без параметрів
CalcA IncrA = delegate
{
    // "захоплення" зовнішньої змінної a
    a = a + 1; // інкремент
};

// Демонстрація використання ("захоплення") зовнішньої змінної a
a = 8;

IncrA(); // a = 9
IncrA(); // a = 10

 

11. Що означає термін “захоплення змінної”? Приклад

Термін “захоплення змінної” означає використання зовнішньої змінної в анонімному методі. Захоплена змінна існує до тих пір, поки делегат, що її захопив, не буде “зібраний в сміття”.
Більш детально про “збір сміття” описано в темі:

Приклад

У прикладі продемонстровано захоплення змінної a. Приклад приведено для додатку типу Windows Forms Application. У класі основної форми оголошено два типи делегатів з іменами CalcA1, CalcA2.

В обробнику події оголошено два делегати:

  • делегат IncrA типу CalcA1. Цей делегат збільшує на 1 значення зовнішньої змінної a;
  • делегат IncrA2 типу CalcA2. Цей делегат збільшує значення зовнішньої змінної a на 2.

Делегати IncrA та IncrA2 здійснюють захоплення зовнішньої змінної a.

Увесь текст модуля “Form1.cs” наступний:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace TrainDelegates07
{
    public partial class Form1 : Form
    {
        // зовнішня змінна a
        private int a;

        // тип делегату CalcA1
        delegate void CalcA1();

        // тип делегату CalcA2
        delegate void CalcA2();

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            // Оголошення анонімного методу
            CalcA1 IncrA = delegate
            {
                // "захоплення" зовнішньої змінної a
                a = a + 1; // збільшення a на 1
            };

            // анонімний метод IncrA2
            CalcA2 IncrA2 = delegate
            {
                // "захоплення" зовнішньої змінної a
                a = a + 2; // збільшення a на 2
            };

            // Демонстрація "захоплення" зовнішньої змінної a
            a = 8;

            IncrA(); // a = 9
            IncrA(); // a = 10

            IncrA2(); // a = 12, взято попереднє значення a
        }
    }
}

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

  • делегат з іменем IncrA типу CalcA1. Цей делегат посилається на анонімний метод, що збільшує значення зовнішньої змінної a на 1;
  • делегат з іменем IncrA2 типу CalcA2. Цей делегат посилається на анонімний метод, що збільшує значення зовнішньої змінної a на 2.

Після виклику делегатів IncrA та IncrA2 значення змінної a змінюється. Змінна a існує в межах класу Form1.

 


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