Я читал репозиторий PHP дизайна доменного диска, созданный CodelyTv, который является моделью для создания новых решений с использованием этой методологии, когда я нашел кое-что интересное для выполнения в будущих сценариях. Я прочитал следующий фрагмент кода:

use function Lambdish\Phunctional\repeat;

final class Repeater
{
    public static function repeat(callable $function, $quantity): array
    {
        return repeat($function, $quantity);
    }

    public static function repeatLessThan(callable $function, $max): array
    {
        return self::repeat($function, IntegerMother::lessThan($max));
    }

    public static function random(callable $function): array
    {
        return self::repeat($function, IntegerMother::lessThan(5));
    }
}

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

Поэтому мы можем выполнить случайные методы следующим образом:

Repeater::random(CourseIdMother::creator());
Repeater::random(IntegerMother::random());

В первой строке результатом является список из N элементов, являющихся результатом CourseIdMother::creator(), а во второй строке — список из N элементов типа int. Также существует другой метод под названием repeatLessThan, с помощью которого мы можем указать максимальное количество объектов, которые мы хотим сохранить в списке.

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

Методы делегирования — Введение.

Метод делегата — это переменная ссылочного типа, которая содержит ссылку на метод и может быть изменена во время выполнения. Он особенно используется для реализации событий и методов обратного вызова.

Существует три этапа определения и использования делегатов:

  1. Заявление нашего делегата.
  2. Создание экземпляра, создание объекта делегата.
  3. Вызов, когда мы вызываем ссылочный метод.
//Declaration
public delegate void WriterDelegate(string text);
class Program
{
    public static void Write(string text)
    {
        Console.WriteLine(text);
    }

    static void Main(string[] args)
    {
        //Instantiation
        WriterDelegate writerDelegate = new WriterDelegate(Write);

        //Invocation
        writerDelegate("Some example text.");
    }
}

Кроме того, в C# есть два встроенных делегата: Func<T> и Action<T>.

Действие — это своего рода метод делегатов, который имеет до шестнадцати параметров и не возвращает никакого результата. Таким образом, мы можем назначать этому делегату только методы с возвращаемым типом void.

В противном случае Func имеет до шестнадцати параметров и возвращает результат. Другими словами, мы используем делегат Func только с методом, тип результата которого отличается от void.

Я не хочу расширять эту статью теорией, но рекомендую ознакомиться с этой документацией, чтобы понять, как можно простым способом использовать методы Action и Func.

Методы делегата — Пример.

С помощью Generics в C# мы можем создать аналогичный случайный метод, как показано в первой части этой статьи, используя в качестве параметра отправку Func.

private static IEnumerable<T> Repeat(Func<T> method, int quantity)
{
   for (int i = 0; i < quantity; i++)
   {
       yield return method();
   }
}

С помощью Repeat(Func<T> method, int quantity) мы можем выполнить Func N раз, а результат сохранить в IEnumerable<T>. Весь класс Repeater<T> приводит к:

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

public class Repeater<T>
{
    private static IEnumerable<T> Repeat(Func<T> method, int quantity)
    {
        for (int i = 0; i < quantity; i++)
        {
            yield return method();
        }
    }

    public static IEnumerable<T> RepeateLessThan(Func<T> method, int max)
    {
        return Repeat(method, IntegerMother.LessThan(max));
    }

    public static IEnumerable<T> Random(Func<T> method)
    {
        return Repeat(method, IntegerMother.LessThan(5));
    }
}

Он очень похож на исходный код. Наконец, мы можем использовать вспомогательный класс Repeater<T> следующими способами:

Repeater<CourseId>.Random(CourseIdMother.Random);
Repeater<int>.Random(IntegerMother.Random);
Repeater<string>.RepeateLessThan(StringMother.Random,20);

Как мы видим, метод генерирует список объектов, выполняя Func<T>. Он всегда возвращает объект того же типа, который указан в контракте (CourseId в первом примере).

Другим примером часто используемого делегата является шаблон репозиторий с выражениями. Мы можем создать метод Get, который выполняет предложение where, определенное другим методом, и возвращает объект IQueryable.

public abstract class RepositoryBase<T> : IRepositoryBase<T> where T : class
{
    protected RepositoryContext RepositoryContext { get; set; }

    public RepositoryBase(RepositoryContext repositoryContext)
    {
        this.RepositoryContext = repositoryContext;
    }

    public IQueryable<T> FindAll()
    {
        return this.RepositoryContext.Set<T>();
    }

    public IQueryable<T> FindByCondition(Expression<Func<T, bool>> expression)
    {
        return this.RepositoryContext.Set<T>()
            .Where(expression);
    }
}

Используя этот подход, мы могли бы отправить в качестве параметра предложение where, созданное выражением LinQ, следующим образом:

await FindByCondition(o => o.Id.Equals(ownerId))             
             .SingleAsync();

await FindByCondition(o => o.Age > 10 && o.Name.Contains(ownerName))             
             .SingleAsync();

Существует множество применений и потенциальных сценариев для методов делегата в C#, но в этой статье показан простой пример, чтобы понять, как мы можем использовать такой инструмент, предоставляемый языком.

Microsoft — использование делегатов
Зачем делегаты
Code Maze — делегаты

Первоначально опубликовано на https://dev.to