Шаг 170.
Язык программирования C#. Начала.
Делегаты и события. Использование делегатов (продолжение)

    На этом шаге мы рассмотрим пример использования делегата для передачи ссылки на методы аргументом другому методу.

    В следующем примере мы используем делегат для того, чтобы передавать ссылки на методы аргументом другому методу. Программа достаточно простая: описывается статический метод, который используется для того, чтобы создать таблицу значений другого метода. Таблица формируется так. Берется некоторый метод, у которого целочисленный аргумент и который возвращает целочисленный результат. Аргумент метода изменяется в заданных пределах. Для каждого значения аргумента отображается значение метода. Этот простой алгоритм не зависит от того, для какого именно метода строится таблица значений. Главное, чтобы у метода был целочисленный аргумент, и он должен возвращать целочисленный результат. Именно та ситуация, когда разумно использовать делегаты. Рассмотрим программный код, представленный ниже.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace pr170_1
{
    // Объявление делегата: 
    delegate int MyDelegate(int n);
    
    // Класс с главным методом: 
    class Program
    {
        // Статический метод для вычисления нечетных чисел: 
        static int f(int n) { 
            return 2 * n + 1;
        }
        // Статический метод для вычисления четных чисел: 
        static int g(int n) { 
            return 2 * n;
        }
        // Статический метод для вычисления квадратов чисел: 
        static int h(int n) { 
            return n * n;
        }
        // Статический метод, которому аргументом 
        // передается ссылка на метод: 
        static void display(MyDelegate F, int a, int b) { 
            Console.WriteLine("{0, -4}| {1, 4}", "x", "F(x)");
            Console.WriteLine("----------");
            for(int k = a; k <= b; k++) {
                // Команда с вызовом экземпляра делегата: 
                Console.WriteLine("{0,-4}|{1,4}", k, F(k));
            }
            Console.WriteLine();
        }

        // Главный метод: 
        static void Main()
        {
            // Диапазон изменения аргумента: 
            int a = 0, b = 5;
            Console.WriteLine("Нечетные числа:");
            // Передача аргументом ссылки на метод: 
            display(f, a, b);
            Console.WriteLine("Четные числа:");
            // Передача аргументом ссылки на метод: 
            display(g, a, b);
            Console.WriteLine("Числа в квадрате:");
            // Передача аргументом ссылки на метод: 
            display(h, a, b);
            // Задержка:
            Console.ReadLine();
        }
    }
}
Архив проекта можно взять здесь.

    В результате выполнения программы получаем следующее:


Рис.1. Результат выполнения программы

    Программа небольшая и простая. В программе командой

  delegate int MyDelegate(int n);
объявляется делегат, экземпляр которого может ссылаться на метод, имеющий целочисленный аргумент и возвращающий целочисленный результат. В классе с главным методом программы описано еще несколько статических методов. Методы f(), g() и h() соответствуют параметрам делегата MyDelegate: у каждого из этих методов один целочисленный аргумент, и каждый метод результатом возвращает целое число. При заданном целочисленном аргументе n метод f() возвращает значение 2*n+1 (нечетное число), метод g() возвращает значение 2*n (четное число), а метод h() возвращает значение n*n (число в квадрате). Еще один статический метод display() описан с тремя аргументами. Первый аргумент F имеет тип MyDelegate - то есть это переменная, которая может ссылаться на экземпляр делегата. Мы уже знаем, что такой переменной можно присваивать ссылку на метод. Поэтому при вызове метода первым аргументом можно передавать ссылку на метод (с целочисленным аргументом и целочисленным результатом). Другими словами, под аргументом F мы можем подразумевать название метода, который можно вызывать, передав ему целочисленный аргумент. Еще два целочисленных аргумента (а и b) определяют диапазон, на котором табулируется переданный первым аргументом метод. Табуляция выполняется просто: с помощью цикла в консоль выводится значение аргумента k и значение метода F(k).


В командах
  Console.WriteLine("{0, -4}| {1, 4}", "x", "F(x)");
и
  Console.WriteLine("{0,-4}|{1,4}", k, F(k));
инструкция {0, -4} означает, что под отображаемое значение выделяется 4 позиции и выравнивание выполняется по левому краю. Инструкция {1, 4} означает, что под отображаемое значение выделяется 4 позиции и выравнивание выполняется по правому краю.

    В главном методе программы при заданных значениях переменных a и b командами

  display(f, a, b);   , 
  display(g, a, b);   и 
  display(h, a, b); 
табулируются методы f(), g() и h() соответственно. Чтобы передать метод аргументом методу display(), достаточно указать имя метода первым аргументом метода display(). Например, при выполнении команды
  display(f, a, b); 
выполняется код метода display(), но только вместо аргумента F в программном коде следует подразумевать f. То же касается и других команд с вызовом display().

    На следующем шаге мы продолжим изучение этого вопроса.




Предыдущий шаг Содержание Следующий шаг