Добавить в корзинуПозвонить
Найти в Дзене
"Мы"-Прогер

Изучаем C# - Функция на входе функции

Что такое функции. Стек вызовов - https://dzen.ru/a/aZW_Jhjy_jZrxPm2?share_to=link Написание функций - https://dzen.ru/a/aZbtZZfd7wnFve40?share_to=link Не забудьте вернуть Git на ветку master после изучения веток в гите. Итак, от предыдущих экспериментов у нас остался класс DeliveryTask ("Задача доставки") и список data из объектов этого класса: Также у нас была функция по поиску приоритетных задач доставки: Если у вас нет этого кода, напишите его. Сначала разберём тему в упрощённом понимании. Я не буду сразу рассказывать вам про делегаты, потому что это слишком сложно. Потом. В функции FilterPrioriryTask() (см. предыдущий набросок кода) создавался список для результатов, затем мы в цикле проходились по данному нам списку и для каждого элемента списка проверяли условие. Как вы можете догадаться, фильтрация списков по какому-либо условию - это часто встречающаяся задача. Например, список приказов должен позволять искать приказы за определённые даты, приказы, связанные с указанным челове
Оглавление

В предыдущих статьях:

Что такое функции. Стек вызовов - https://dzen.ru/a/aZW_Jhjy_jZrxPm2?share_to=link

Написание функций - https://dzen.ru/a/aZbtZZfd7wnFve40?share_to=link

Подготовка

Не забудьте вернуть Git на ветку master после изучения веток в гите.

Итак, от предыдущих экспериментов у нас остался класс DeliveryTask ("Задача доставки") и список data из объектов этого класса:

В файле DeliveryTask.cs
В файле DeliveryTask.cs
В файле Program.cs
В файле Program.cs

Также у нас была функция по поиску приоритетных задач доставки:

-3

Если у вас нет этого кода, напишите его.

Функция на входе функции

Сначала разберём тему в упрощённом понимании. Я не буду сразу рассказывать вам про делегаты, потому что это слишком сложно. Потом.

В функции FilterPrioriryTask() (см. предыдущий набросок кода) создавался список для результатов, затем мы в цикле проходились по данному нам списку и для каждого элемента списка проверяли условие. Как вы можете догадаться, фильтрация списков по какому-либо условию - это часто встречающаяся задача. Например, список приказов должен позволять искать приказы за определённые даты, приказы, связанные с указанным человеком, приказы, находящиеся в определённом статусе и так далее. Список сотрудников должен позволять находить сотрудников определённого отдела, сотрудников, которым ещё не выплатили зарплату и так далее. Во всех подобных случаях у нас есть список и мы должны отфильтровать его по определённому условию. Причём всегда нужно создать список с ответами, всегда нужно пройтись в цикле по исходному списку, всегда нужно добавлять в результат те элементы, для которых условие истинно. В общем, во всех этих случаях весь код функции фильтрации один и тот же, меняется только условие. Поэтому вместо создания многих разных функций фильтрации, в которых почти весь код будет дублироваться, давайте сделаем нашу функцию фильтрации универсальной - пусть она фильтрует список по любым условиям, а условия будем подавать ей на вход. Какого типа данных будут входной аргумент для этих условий? Поскольку условия могут быть любыми, то это какой-то блок кода. А что такое блок кода? Это функция. Итак, мы должны получать на вход функцию. А что должна получать на вход эта функция? Чтобы мы могли в ней проверять любые условия про задачу доставки, нам надо иметь целиком эту задачу. Получается, что функция проверки условия должна принимать на вход целиковую задачу, то есть переменную класса DeliveryTask. А какой тип данных должна выдавать эта функция? Очевидно, раз она проверяет условие, её результатом будет true либо false, то есть, тип данных bool. Напишем пример такой функции с тем условием, которое у нас есть сейчас (проверяет задачу на приоритет не ниже 3):

-4

Здесь результатом сравнения является true/false, то есть, bool, который и выдаётся в ответ. Функция названа CheckPriority(), потому что она проверяет приоритет.

Но как получить эту функцию на вход функции FilterPriorityTasks()? Добавим к функции FilterPriorityTasks() второй входной аргумент - функцию типа данных Func<DeliveryTask, bool>. Тип данных Func<DeliveryTask, bool> означает функцию, которая принимает на вход один аргумент типа DeliveryTask и выдаёт ответ типа bool. А если бы функция получала бы на вход два целых числа, то её тип данных был бы Func<int, int, bool>. В общем случае, все параметры типа у Func<...>, кроме последнего - это то, что подаётся на вход функции, а последний - это то, что она возвращает в ответ. Положим её в переменную condition ("условие"):

-5

Теперь в if просто вызовем эту функцию, передав ей на вход то, что она должна принимать (задачу доставки, проверить которую мы хотим). Для вызова просто припишем скобки к переменной, которая хранит эту функцию:

-6

Теперь функция FilterPriorityTasks() умеет проверять любое условие, поэтому надо её переименовать в FilterTasks(). Для этого нажмём на её названии правой кнопкой и выберем в меню Refactor - Rename.

Осталось вызвать функцию FilterTasks():

-7

На место второго аргумента мы подаём функцию CheckPriority. Обратите внимание, что мы пишем её без скобок. Это потому, что мы не вызываем её здесь. Если бы мы приписали круглые скобки, то это означало бы вызов функции, и вместо функции с круглыми скобками туда был бы подставлен её результат.

Проверим - всё работает, как и раньше. Зато теперь мы легко можем вместо CheckPriority() подставить любую другую функцию-условие.

Далее

Далее мы разберём упрощённый синтаксис для функций и библиотеку Linq для работы со списками - https://dzen.ru/a/aZmfY9iSwn75mNFy?share_to=link

Оглавление - https://dzen.ru/a/aXisxwt_Mnz2qTjs?share_to=link