• Добро пожаловать на сайт - Forumteam.men !

    Что бы просматривать темы форума необходимо зарегестрироваться или войти в свой аккаунт.

    Группа в телеграме (подпишитесь, что бы не потерять нас) - ForumTeam Chat [Подписатся]
    Связь с администратором - @ftmadmin

34. Знакомимся с делегатами.

Redman

<FORUMTEAM>
Команда форума
Регистрация
13.11.17
Сообщения
13.343
Реакции
8.371
Баллы
1.200
FTC
203¢
Делегаты.
Делегат, какое знакомое слово .... Вспоминается СССР: “Делегаты съезда ….” В C# к счастью под понятием делегата не маскируется тот человек, которого послал народ на очередной пленум. Итак, что же это?
Делегат – это так называемый “безопасный указатель на функцию”. Однако, в отличие от обычных указателей на функцию в С++, делегаты C# могут вызывать более одной функции (при совместном комбинировании двух делегатов результатом будет делегат, который вызывает их обоих). В чем состоит “безопасность” ? В С++ указатель на функцию – это фактически просто адрес, делегат же позволяет проверять количество передаваемых параметров, возвращаемое значение и т.д..Как вы уже привыкли многие конструкции C# - это классы, так и делегат - это класс отнаследованный от базового класса System.MulticastDelegate.Делегат можно объявлять как в классе, так и просто в пространстве имен.Рассмотрим синтаксис объявления делегата:
Код:
спецификатор_доступа delegate тип_возвр_значения_для_метода Имя_Делегата(список_параметров_метода)

Небольшие комментарии к приведенному выше: 1)спецификатор_доступа - например, public и т.д. 2)delegate говорит о том что, объявляется делегат 3)тип_возвр_значения_для_метода, список_параметров_метода - определяет, на что может указывать делегат. Например:
Код:
public delegate void SetFire()

Читается это так – SetFire – это делегат на метод возвращаюший void, и не принимающий параметров.На первый взгляд всё прозрачно, однако что же мы сделали на самом деле? SetFire – это класс, который автоматически отнаследовался от System.MulticastDelegate и получил поля и методы базового класса , т.е. вот что было на самом деле:
Код:
public class SetFire:System.MulticastDelegate

Делегат может указывать как на обычный метод так и на статический.Настало волшебное время - мы применим полученную о делегатах информацию во благо обществу, т.е. рассмотрим практический пример, с использованием Делегатов:
Код:
using System;
using System.Collections;
class Human{
// Делегат на функцию, которая ничего не возвращает и принимает объект типа h
public delegate void HumanDelegate(Human h);
// Перечисление
public enum Sex{Male,Female};
private Sex p;
private string name;
private string surname;
private int age;
// конструктор
public Human(){
     name = surname = "Нет Данных";
     age = 0;
     p = Sex.Male;
}
// конструктор с параметрами
public Human(string name,string surname,int age,Sex p){
     this.name = name;
     this.surname = surname;
     this.age = age;
     this.p = p;
}
// Задание имени, возврат его
public string Name{
     get{
         return name;
     }
     set{
         name = value;
     }
}
// Задание фамилии, возврат её
public string Surname{
     get{
         return name;
     }
     set{
        name = value;
     }
}
// Задание возраста, возврат его
public int Age{
     get{
         return age;
     }
     set{
         age = value;
     }
}
// Задание пола,возврат его
public Sex RealSex{
     get{
         return p;
     }
     set{
         p = value;
     }
}
}
//Класс, содержащий людей
class Firm{
    ArrayList people = new ArrayList();
    public Firm(){
        // Добавляем в список 3 - х людей
        people.Add(new Human());
        people.Add(new Human("Вася","Иванов",80,Human.Sex.Male));
        people.Add(new Human("Катерина","Маркова",25,Human.Sex.Female));

    }
    // Метод, принимающий делегат, четко указывается  название класса,
    //где содержится делегат, а также название делегата
    public void AnalyzePeople(Human.HumanDelegate ptr){
        Console.WriteLine("Будем выполнять действия над человеком !!!");
        // Вызываются методы, на которые указывает делегат
        foreach(Human obj in people)
            ptr(obj);
    }
}

class Sample
{
    // Проверка пола   
    static void AnalyzeSex(Human h){
        if(h.RealSex==Human.Sex.Male){
            Console.WriteLine("Мужчина");
        }
        else{
            Console.WriteLine("Женщина");

        }
    }
    // Проверка по возрасту
    static void AnalyzeAge(Human h){
        if(h.Age>65){
            Console.WriteLine("Больше 65 лет");
        }
        else{
            Console.WriteLine("Меньше или равно 65 лет");

        }
    }

    static void Main()
    {
        Console.WriteLine("Пример работы Делегата");
        Firm firm = new Firm();
        // В этой строке происходит использование делегатов. Создаётся объект                 // делегата используя
        // ключевое слово new.
        // Сейчас делегат указывает на метод AnalyzeSex
        firm.AnalyzePeople(new Human.HumanDelegate(AnalyzeSex));
        // Сейчас делегат указывает на метод AnalyzeAge
        firm.AnalyzePeople(new Human.HumanDelegate(AnalyzeAge));
        Console.Read();
    }
}

Вывод:

Пример работы Делегата
Будем выполнять действия над человеком !!!
Мужчина
Мужчина
Женщина
Будем выполнять действия над человеком !!!
Меньше или равно 65 лет
Больше 65 лет
Меньше или равно 65 лет

Обратите внимание на то, что у нас сейчас делегат, вложенный в класс и поэтому для доступа к нему мы используем имя класса:
Код:
firm.AnalyzePeople(new Human.HumanDelegate(AnalyzeAge));

Как уже было сказано выше делегат это класс отнаследованный от System.MulticastDelegate. Рассмотрим 2 полезных метода этого базового класса. Первый метод Combine – этот статический метод используется для создания делегата, указывающего на несколько разных функций (также можно пользоваться перегруженным оператором +), второй Remove - этот статический метод удаляет делегат из списка указателей на функции. Если делегат указывает на несколько методов, то тогда при вызове делегата будут вызываться методы,на которые указывает делегат. Например(те же самые классы другой Main):
Код:
static void Main(){
        Console.WriteLine("Пример работы Делегата");
        Firm firm = new Firm();
        // Создание делегатов
        Human.HumanDelegate sex = new Human.HumanDelegate(AnalyzeSex);
        Human.HumanDelegate age = new Human.HumanDelegate(AnalyzeAge);

        // Многоадресный Делегат (формируем его через +)
        // Произойдет вызов методов AnalyzeSex и AnalyzeAge
        firm.AnalyzePeople(sex+age);
        Console.WriteLine("\n\n");
        // Многоадресный Делегат (формируем его через +)
        // Произойдет вызов методов AnalyzeSex и AnalyzeAge
        firm.AnalyzePeople(age+sex);
       
        // Или так тоже Многоадресный Делегат
        Console.WriteLine("\n\n");
        // Многоадресный Делегат (формируем его через Combine)
        // Произойдет вызов методов AnalyzeSex и AnalyzeAge
        firm.AnalyzePeople((Human.HumanDelegate)Delegate.Combine(sex,age));
        // Или так тоже можно
        MulticastDelegate del = age+sex;
        firm.AnalyzePeople((Human.HumanDelegate)del);
        // Удаляем один делегат
        Delegate onlysex = MulticastDelegate.Remove(del,age);
        Console.WriteLine("\n\n************************************\n\n");
        // Уже не многоадресный делегат
        firm.AnalyzePeople((Human.HumanDelegate)onlysex);

        Console.Read();
}

Сейчас мы через делегат вызывали статические методы класса, но это можно делать и с обычными. Для этого надо чуть-чуть видоизменить создание делегата. Например:
Код:
Firm firm = new Firm();
// Test - это какой-то класс в нем есть методы AnalyzeSex,
// AnalyzeAge
Test test = new Test();
//
firm.AnalyzePeople(new Human.HumanDelegate(test.AnalyzeSex));
firm.AnalyzePeople(new Human.HumanDelegate(test.AnalyzeAge));
 
Сверху Снизу