Я читал репозиторий 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
, с помощью которого мы можем указать максимальное количество объектов, которые мы хотим сохранить в списке.
Возвращаясь к моему введению, я читал этот код, когда подумал, что это хороший сценарий для объяснения того, как мы можем использовать делегаты или вызываемые методы.
Методы делегирования — Введение.
Метод делегата — это переменная ссылочного типа, которая содержит ссылку на метод и может быть изменена во время выполнения. Он особенно используется для реализации событий и методов обратного вызова.
Существует три этапа определения и использования делегатов:
- Заявление нашего делегата.
- Создание экземпляра, создание объекта делегата.
- Вызов, когда мы вызываем ссылочный метод.
//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