На этом шаге мы рассмотрим простой пример использования делегата.
Перейдем к практическим моментам. В примере ниже представлена программа, в которой объявляются делегаты, создаются экземпляры делегатов и затем эти экземпляры делегатов используются для вызова методов.
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).
Статический метод getFirst() с целочисленным аргументом k и текстовым аргументом txt возвращает результатом символ из текста txt с индексом k (выражение txt[k]).
В классе Program, в котором описан главный метод Main(), есть описание еще одного статического метода getLast(). Метод для заданного текста txt (второй аргумент) возвращает символ из этого текста с индексом k (первый аргумент), если индекс отсчитывать с конца текста (результат вычисляется как txt[txt.Length-k-1]).
В методе Main() командой
MyClass obj = new MyClass(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;
Командой
meth = MyClass.getFirst;
Командой
meth = getLast;
На следующем шаге мы рассмотрим многократную адресацию.