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

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

    Перейдем к практическим моментам. В примере ниже представлена программа, в которой объявляются делегаты, создаются экземпляры делегатов и затем эти экземпляры делегатов используются для вызова методов.

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

namespace pr167_1
{
    // Объявление делегата:
    delegate char MyDelegate(int k, string txt);

    // Класс: 
    class MyClass {
        // Целочисленное поле: 
        public int code;
        // Конструктор: 
        public MyClass(int n) { 
            code = n;
        }
        // Нестатический метод с двумя аргументами: 
        public char getChar(int k, string txt) { 
            return (char)(txt[k] + code);
        }
        // Статический метод с двумя аргументами: 
        public static char getFirst(int k, string txt) { 
            return txt[k];
        }
    }

    // Класс с главным методом: 
    class Program
    {
        // Статический метод с двумя аргументами: 
        static char getLast(int k, string txt) {
            return txt[txt.Length - k - 1];
        }
        // Главный метод: 
        static void Main()
        {
            // Создание объекта:
            MyClass obj = new MyClass(5);
            // Создание экземпляра делегата:
            MyDelegate meth = new MyDelegate(obj.getChar);
            // Вызов экземпляра делегата:
            Console.WriteLine("Символ \'{0}\'", meth(4, "Alpha")); 
            // Присваивание значения полю объекта: 
            obj.code = 1;
            // Вызов экземпляра делегата:
            Console.WriteLine("Символ \'{0}\'", meth(4, "Alpha")); 
            // Присваивание нового значения переменной делегата: 
            meth = MyClass.getFirst;
            // Вызов экземпляра делегата:
            Console.WriteLine("Символ \'{0}\'", meth(2, "Alpha")); 
            // Присваивание нового значения переменной делегата: 
            meth = getLast;
            // Вызов экземпляра делегата:
            Console.WriteLine("Символ \'{0}\'", meth(1, "Alpha"));
            // Задержка:
            Console.ReadLine();
        }
    }
}
Архив проекта можно взять здесь.

    Результат выполнения программы такой:


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

    Делегат MyDelegate в программе объявляется инструкцией

  delegate char MyDelegate(int k, string txt);   . 

    Такое объявление означает, что экземпляр делегата может ссылаться на метод, который результатом возвращает значение типа char и имеет два аргумента: первый типа int и второй типа string.

    В программе описывается класс MyClass. В классе описано открытое целочисленное поле code и конструктор с одним аргументом (аргумент задает значение поля объекта). Еще в классе описано два метода: нестатический и статический. У каждого из них два аргумента (целое число и текст), и каждый из них возвращает результатом символьное значение. Оба метода соответствуют характеристикам делегата MyDelegate, и поэтому экземпляр делегата сможет ссылаться на эти методы.

    Нестатический метод getChar() имеет два аргумента: k (целое число) и txt (текст). Результатом возвращается символ, вычисляемый выражением (char)(txt[k] + code).


Из текста txt берется символ с индексом k (выражение txt[k]), к коду полученного символа прибавляется значение поля code (выражение txt[k]+code), и полученное число преобразуется к текстовому формату (выражение (char)(txt[k]+code)). Получается, что результатом является символ, смещенный к символу txt[k] на количество позиций, определяемое значением поля code.

    Статический метод getFirst() с целочисленным аргументом k и текстовым аргументом txt возвращает результатом символ из текста txt с индексом k (выражение txt[k]).

    В классе Program, в котором описан главный метод Main(), есть описание еще одного статического метода getLast(). Метод для заданного текста txt (второй аргумент) возвращает символ из этого текста с индексом k (первый аргумент), если индекс отсчитывать с конца текста (результат вычисляется как txt[txt.Length-k-1]).

    В методе Main() командой

  MyClass obj = new MyClass(5); 
создается объект obj класса MyClass, значение поля code объекта obj равно 5.

    Экземпляр делегата MyDelegate создается командой

  MyDelegate meth = new MyDelegate(obj.getChar);   . 

    В итоге мы получаем переменную meth делегата MyDelegate, которая ссылается на экземпляр делегата, ссылающийся на метод getChar() объекта obj. Поэтому при вызове экземпляра делегата инструкцией meth(4, "Alpha") из объекта obj вызывается метод getChar() с аргументами 4 и "Alpha". В результате из текста "Alpha" берется символ с индексом 4 (это символ 'a') и выполняется смещение на 5 позиций. В результате получаем символ 'f '.

    Далее мы командой

  obj.code = 1;
меняем значение поля code объекта obj и снова вызываем экземпляр делегата с теми же аргументами (команда meth(4, "Alpha")). Теперь результатом является символ 'b', поскольку к символу 'a' применяется смещение на 1 позицию (новое значение поля code), а не на 5 (старое значение поля code), как было ранее.

    Командой

  meth = MyClass.getFirst;
переменной meth делегата MyDelegate присваивается новое значение: ссылка на статический метод getFirst() класса MyClass. После этого вызов экземпляра делегата командой meth(2, "Alpha") означает вызов статического метода getFirst() с аргументами 2 и "Alpha". Результатом является символ 'p' (символ с индексом 2 в тексте "Alpha").

    Командой

  meth = getLast;
экземпляру делегата meth в качестве значения присваивается ссылка на статический метод getLast(). Поскольку команда присваивания находится (в главном методе) в том же классе, в котором описан статический метод getLast(), то имя класса в ссылке на метод можно не указывать. При вызове экземпляра делегата командой meth(1, "Alpha") вызывается метод getLast() с аргументами 1 и "Alpha". Результатом является символ 'h': второй индекс с конца текста "Alpha".

    На следующем шаге мы рассмотрим многократную адресацию.




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