ДЕЛЕГАТЫ в C# и Asp Net Core на практике — Transcript

Видео объясняет делегаты в C# и Asp Net Core с практическими примерами и их применением в современном программировании.

Key Takeaways

  • Делегаты — это ссылки на методы, которые позволяют передавать поведение как параметр.
  • Использование делегатов улучшает дизайн, разделяя ответственность и повышая гибкость кода.
  • В C# есть стандартные generic делегаты, упрощающие работу с методами.
  • Делегаты широко применяются в Asp Net Core для конфигурации и обработки событий.
  • Понимание делегатов важно для эффективной разработки и успешного прохождения технических собеседований.

Summary

  • Объяснение концепции делегатов в C# и их важности в современной веб-разработке на .NET Core.
  • Разбор примера калькулятора с операциями сложения и вычитания для демонстрации проблем с ответственностью класса.
  • Показано улучшение дизайна через использование интерфейсов и делегатов вместо строковых параметров.
  • Подробное объяснение синтаксиса делегатов и как они представляют ссылки на методы.
  • Демонстрация различных способов передачи методов в качестве делегатов, включая локальные и анонимные методы.
  • Обзор стандартных шаблонных делегатов (generic delegates) для упрощения кода.
  • Примеры использования делегатов для фильтрации данных и выполнения действий над коллекциями.
  • Обсуждение преимуществ делегатов в контексте расширяемости и поддержки кода.
  • Показано применение делегатов в настройке и конфигурации компонентов Asp Net Core.
  • Рекомендации по изучению делегатов для успешного прохождения собеседований и повышения квалификации.

Full Transcript — Download SRT & Markdown

00:00
Speaker A
Всем привет. Меня зовут Кирилл, и я в этом видео хочу рассказать про делегаты в C#, потому что эта тема вызывает множество вопросов у людей, которые изучают C# и которые уже пишут код на C#, потому что делегаты в современной
00:13
Speaker A
разработке, особенно в современной веб-разработке, они используются везде. И на самом деле, если вы пишете код на том же .NET, то там делегаты тоже повсюду. И вообще они довольно полезные, и поэтому нужно уметь с ними работать.
00:26
Speaker A
Ну и на собеседованиях тоже любят спрашивать различные вопросы про них. Поэтому в этом видео я постараюсь вам полностью рассказать про делегаты, показать с ними реальные примеры, как их можно использовать и где на самом деле в .NET Core они очень много используются и
00:41
Speaker A
почему с ними надо уметь работать. Давайте я сейчас начну рассказывать, примеры показывать, показывать, как использовать делегаты. Ну а вы подпишитесь на канал, поставьте лайк и можете подписаться на мой Telegram-канал. Там больше информации, и я там пишу множество разных постов.
00:56
Speaker A
Хорошо, давайте приступим. Смотрите, мы видим VT-калькулятор. То есть сначала я вам просто покажу примеры с стандартным синтаксисом, чтобы любой новичок, любой человек мог разобраться, что такое делегат и как его можно использовать.
01:09
Speaker A
Предположим, я хочу разработать калькулятор, который выполняет, ну, какие-то числовые операции, то есть операции с числами. Вот у меня есть метод performCalculation, у меня есть метод add, subtract, то есть там на а сложение, на вычитание, и есть метод,
01:24
Speaker A
который выполняет какую-то операцию. Вот у него сигнатура следующая. Он принимает параметр X, Y и какую-то строку операцию, то есть строку, которая определит, какую должен этот калькулятор выполнить операцию. То есть здесь с помощью switch-case мы проверяем, что это за операция. И в зависимости от того,
01:44
Speaker A
что ввел пользователь, мы используем тот или иной метод. Вот какие минусы у этого класса. Этот класс имеет сразу несколько ответственностей. Во-первых, он хранит в себе различные операции.
01:56
Speaker A
Во-вторых, он отвечает за выполнение именно какой-то операции. В-третьих, он ещё и решает, то есть выбирает, валидирует эти операции, решает, какую операцию конкретно нужно выполнить. То есть мы видим, что ответственности у этого класса довольно много. Ну и дизайн
02:13
Speaker A
у этого довольно плохой. То есть, если нам придётся его расширять, а увеличивать функционал, то мы столкнёмся с проблемами. Вот как можно это обойти?
02:21
Speaker A
На самом деле, можно это обойти стандартным способом через ООП. Допустим, мы хотим вместо вот этой строки принимать, допустим, интерфейс IOperation. Ну, сделать какой-нибудь такой интерфейс. У нас может быть несколько классов, которые реализуют этот интерфейс. Допустим,
02:40
Speaker A
AddOperation, который у нас добавляет, то есть складывает числа, то есть он вернёт просто a плюс b, допустим, да. И получается, что здесь мы принимаем операцию. Вот это всё нам больше не нужно, потому что у нас
02:53
Speaker A
клиент решает, какая операция будет передаваться, ну и кто будет её выполнять. То есть это уже решает не сам калькулятор, а допустим какой-то клиентский код, который вызывает вот этот метод. Он решит, что это будет за операция, и он может просто обратиться к
03:07
Speaker A
этому operation и вызвать calculate и передать там необходимые параметры. Сохранить этот result, что-то здесь сделать. Здесь, допустим, может быть валидация. То есть мы видим, что, ну, в принципе, да, мы улучшили структуру.
03:19
Speaker A
Здесь эти методы теперь нам могут вообще не понадобиться. Ну, хотя всё равно хранить какие-то шаблоны, либо доступные операции у этого калькулятора тоже можно. Хорошо. Как теперь нам сделать это с помощью делегатов? И что они нам вообще позволяют сделать? Вот
03:34
Speaker A
представьте, что вместо какого-то объекта, то есть вместо вот этого интерфейса, здесь мы хотим принять не объект какой-то, не класс, а мы хотим принять саму операцию, ну, само действие. Вот как нам это сделать? И вот здесь нам на помощь приходят именно
03:49
Speaker A
делегаты. Мы можем взять и создать здесь, предположим, делегат. А как он создаётся? Мы пишем public, указываем ключевое слово delegate и пишем сигнатуру этого делегата. Предположим, ну, мой делегат, он должен возвращать int, то есть какое-то число, и он будет
04:06
Speaker A
называться CalculateDelegate или, допустим, OperationDelegate. И он будет принимать два параметра. Вот что такое делегат. По сути, делегат — это просто ссылка на метод. То есть теперь мы можем здесь принимать OperationDelegate, назвать это operation. И я сейчас покажу, что здесь
04:25
Speaker A
можно будет сделать. То есть мы можем сказать, что result равен просто operation. Всё. Вот что здесь произойдёт. Давайте я вам сейчас открою сначала класс калькулятор, который я сделал заранее. Вот на нём, ну, тут уже готовый, можно сказать, пример. И здесь
04:39
Speaker A
сейчас я начну объяснять, что такое делегат. По сути, когда мы говорим, что какой-то метод принимает параметр или мы хотим использовать этот делегат, то мы передаём ссылку на метод. То есть мы передаём какое-то действие, которое выполнится, когда мы его вызовем. То
04:55
Speaker A
есть вот здесь вот на тринадцатой строчке мы именно вызываем это действие. Мы вызываем эту операцию, передаём сюда необходимые параметры. Параметры определяются именно сигнатурой. Ну и то, что вернёт делегат, определяется здесь.
05:07
Speaker A
По сути, он очень похож на объявление обычного метода, только если убрать ключевое слово delegate, но и у него нет никакого тела, правильно? То есть это просто по сути метод, только здесь ключевое слово есть delegate, и он становится как бы таким хранилищем для
05:22
Speaker A
метода. Вот. И что мы теперь с этим можем сделать? Мы можем перейти в Program. Давайте сначала посмотрим, как мы вызывали прошлый калькулятор. Ну, допустим, у нас есть VT-калькулятор. Вот мы его здесь видим. Здесь происходит его вызов. То есть сначала мы создаём
05:35
Speaker A
экземпляр VT-калькулятора и у него вызываем метод performCalculation. Пишем, получается, два числа и вызываем метод add либо метод subtract. То есть мы здесь решаем, какой метод вызвать. И мы можем тут любую строку передать, всё, что угодно. Вот мы уже
05:50
Speaker A
поняли, почему этот пример не очень. Слишком много ответственности у этого калькулятора. Как теперь может выглядеть вызов нашего калькулятора, где мы принимаем некий делегат? Вот давайте сейчас продемонстрирую. Предположим, что вы этого не видели, и мы сейчас начнём вызывать его, ну, постепенно сами. Мы
06:09
Speaker A
обращаемся к экземпляру GoodCK и хотим метод вызвать PerformCalculation. Здесь мы указываем два каких-то числа, и сюда мы должны теперь передать делегат. Какие у нас есть способы передать действия? То есть ссылку на метод. Способов есть на самом деле много довольно. Способ первый
06:29
Speaker A
— это передать метод. То есть мы можем здесь, предположим, создать локальный метод Add, который будет принимать два параметра a и b и будет просто складывать эти параметры. То есть мы передаём какой-то метод. Не то, что передаём, мы сделали локальный метод.
06:44
Speaker A
Этот метод может быть нелокальный. Этот метод может лежать где угодно, в принципе. Но суть в том, что мы можем вместо делегата теперь передать этот метод вот таким образом. То есть просто положив именно этот метод, не вызвать этот метод здесь, потому что если мы
06:59
Speaker A
здесь этот метод вызовем и положим здесь, допустим, 10 и 5, то у нас будет ошибка, потому что у нас этот метод возвращает int, а int — это не делегат.
07:10
Speaker A
Если мы посмотрим, что здесь у нас принимает, он ожидает делегат. И вместо делегата мы можем указать метод. Но это может быть до сих пор вам непонятно, поэтому давайте самый такой простой способ. Мы можем создать, допустим, делегат, давайте я его назову delegate
07:28
Speaker A
Add. Следующим образом мы можем просто создавать новый экземпляр нашего MathOperation. MathOperation — это делегат.
07:37
Speaker A
Вот. И чтобы создать новый экземпляр делегата, он здесь принимает по сути тоже делегат. Вот. И в роли вот этого делегата может лежать метод Add. То есть что, ну, что нам нужно, чтобы создать делегат? Нам нужен метод, который будет
07:51
Speaker A
соответствовать сигнатуре делегата. Что это означает? Какая у нас тут сигнатура? У нас тут сигнатура int. То есть этот ме
08:10
Speaker A
делегат - это, ещё раз, это некая структура, которая хранит ссылку на метод либо методы. И это значит, что вот эти, ну, ссылки, которые он будет хранить на методы, они должны эти методы соответствовать сигнатуре, которая определена в этом делегате. Вот. И этот
08:25
Speaker A
метод add, он соответствует, то есть здесь есть intни параметра intзращает int. Вот. И поэтому мы можем этот метод вложить как бы в делегат. И он будет, получается, этот делегат теперь хранить ссылку на этот метод. И на самом деле
08:42
Speaker A
делегат под капотом в cшарпе - это просто класс, который хранит просто ссылку на метод и всё. И поэтому это просто синтетический сахар, который позволяет нам а брать и методы передавать по ссылке. То есть не сразу их выполнять, а передавать по ссылке,
08:59
Speaker A
условно. Поэтому мы можем вот таким способом передать сюда метод. То есть мы можем теперь в калькуляторе вызвать а выполнение какой-то операции и передать метод. Также, то есть мы можем на самом деле не вызывать здесь new math operation, то есть мы можем здесь просто
09:16
Speaker A
сказать, что так, этот делегат будет ссылаться на этот метод. Но в таком случае, если мы посмотрим на тип вот этого делегата, то мы увидим какой-то фанк. Мы сейчас попозже разберём, что такое. И если мы передадим вот этот делегат сюда, то он не сработает. Ну
09:31
Speaker A
ладно, это это сейчас неважно. Мы это потом рассмотрим, почему так происходит и что это вообще значит. В общем, мы можем а передавать делегаты в методы. На самом деле мы можем также а создать, предположим, делегат прошлым образом.
09:45
Speaker A
Math operation передать здесь передать метод add. Мы можем обратиться к этому делегату теперь. И чтобы нам вызвать метод, который лежит в этом делегате, нам нужно просто вызвать метод invok.
09:57
Speaker A
Вот вызвать метод inv. И он принимает тут тоже а и б, то есть 10 и 5. Вот. Ну такой вызов он на самом деле, можно сказать здесь без бессмысленный, потому что что нам мешает просто вызвать метод AD, да, и передать сюда 10,5. И мы
10:12
Speaker A
сейчас как раз-таки рассмотрим, чем полезны делегаты. Ну, как минимум тем, что мы можем теперь сюда передать не только метод AD. Мы можем также сделать, допустим, метод, который будет заниматься вычитанием. То есть по аналогии, допустим, у нас был интерфейс,
10:27
Speaker A
мы делали несколько реализаций. Вот также и тут у нас есть делегат. Мы делаем несколько реализации в в виде вот этих методов. И мы можем передавать различные методы. И получается операция будет уже определяться именно тем методом, который мы передаём. Также,
10:42
Speaker A
ребят, быстренько вам расскажу про мой курс. Если вам интересно, можете послушать. То есть, если вы хотите стать доnetбразработчиком, дойти именно до трудоустройства, а, хорошо научиться писать код. получать ревью, делать разные задания, очень много выполнять практики, смотреть очень много уроков,
10:58
Speaker A
изучать там сложные темы, микросервисы, IPNCore, работа с базой данных и ещё очень много всего, то можете перейти на сайт сочков тире.net.ru либо ко мне в Telegram-канал, можете прямо написать мне. Если вы хотите у меня обучаться, то добро пожаловать. Я обязательно сделаю
11:14
Speaker A
из вас хорошего разработчика. Все самые лучшие практики, все самые лучшие наработки. Я очень много сейчас времени уделяю курсу, очень его сильно развиваю.
11:22
Speaker A
Поэтому, если вам интересно, можете перейти почитать. Я думаю, это того стоит. Все отзывы можно тоже почитать на сайте. То есть все, в принципе, ученики довольны. Если есть какие-то вопросы, то идите ко мне в Telegram-канал. Ещё раз, этот курс он нужен для тех, кто именно
11:36
Speaker A
хочет стать полноценным веб-разработчиком, изучить и эээнд, немножко фронтенда, и devс часть, научиться писать хорошие, масштабируемые производительные веб-приложения на дотнте и устроиться на работу хорошую, там уровня junior Plus, midle. То есть мы изучаем уже довольно сложные темы, не просто там основы cшарпа, а именно
11:54
Speaker A
конкретно серьёзные темы по веб-разработке. Поэтому вам для того, чтобы попасть на курс, нужно уже знать C#P. Поэтому, если есть какие-то вопросы, то пишите мне в Telegram-канал, я там на всё обязательно отвечу. Но такой синтаксис является не самым удобным. То есть нам для этого надо
12:10
Speaker A
создавать методы. На самом деле мы можем передать здесь анонимный метод. То есть с помощью делегатов мы можем ещё и создавать анонимные методы. Как это делается? Мы должны написать ключевое слово делегат, указать здесь сигнатуру этого делегата intдеть анонимный метод. То есть мы должны
12:33
Speaker A
передать именно, что будет делать этот делегат, то есть что будет делать метод, который лежит внутри делегата. И у этого метода как бы не будет названия. Ну, по сути этот метод вернёт просто а + b, да.
12:44
Speaker A
Но такой синтаксис, он довольно неудобный. Им уже никто давно не пользуется. Это старый синтаксис. И чаще всего используют лямбда выражение.
12:54
Speaker A
То есть про лямбда выражение мы тоже поговорим. Но на самом деле лямбда выражение - это просто один из способов.
12:59
Speaker A
То есть это синтаксический сахар, с помощью которого мы можем передать анонимный метод. Что такое анонимный метод? Это метод, который не имеет названия. То есть у него есть там сигнатура, он какую-то выполняет операцию, но он не хранит никакое название. То есть мы таким образом можем
13:17
Speaker A
тоже передать делегат. То есть это будет делегат. Если мы посмотрим на сигнатуру, это будет всё тоже делегат math operation. Он автоматически поймёт, что это operation, потому что он соответствует сигнатуре, потому что, по сути, это просто анонимный метод, который принимает параметр А, параметр B
13:33
Speaker A
и какую-то тут делает операцию. И получается, мы можем вызывать разные операции у этого калькулятора, просто указывая здесь конкретные конкретные действия, что мы хотим делать, допустим, там деление, умножение, там вычитание, сложение и так далее. И можем делать это довольно удобно. То есть уже вот этот,
13:53
Speaker A
ну, класс program, где я это всё вызываю, он решает, какие операции должны тут выполняться. А внутри этого метода происходит просто следующее. мы получаем result и вызываем этот делегат.
14:07
Speaker A
Вот делегат можно вызвать тоже несколькими способами. Можно обратиться к этому делегату и вызвать метод invoke и передать сюда несколько аргументов. То есть это будет то же самое, что если мы просто вызовем вот так вот в кругу в скобочках этот метод. А это является
14:24
Speaker A
современным синтаксисом и в принципе все им пользуются. То есть просто вызывание вот такого вот operation и всё. То есть можно даже operation вызвать здесь. и не получать здесь резал, то есть сразу его здесь вывести, и это будет довольно
14:38
Speaker A
удобно. Но нужно ли нам каждый раз вручную указывать сигнатуру делегата и вручную, так вот для всех операций, предположим, для а разных участков кода создавать свои делегаты? А нам этого делать не нужно, потому что C# разработчики, они сделали это за нас, и
14:56
Speaker A
они создали несколько шаблонных делегатов, которые мы можем удобно использовать. можно использовать вместо нашего делегата math operation шаблонный делегат, то есть generic delegat funk. И почему это тип generic? Потому что он принимает несколько а параметров. То есть мы можем указать, что этот делегат
15:15
Speaker A
должен вернуть int и какие параметры он должен принимать. И перегрузок у этого делегата очень много. То есть мы, а, вместо того, чтобы создавать, предположим, здесь кучу делегатов, где мы принимаем кучу-кучу разных параметров, мы можем передать и указать, ну, конкретно, какие типы мы хотим
15:33
Speaker A
принимать, возвращать. То есть мы можем сказать, что этот делегат только возвращает int, и тогда бы он ничего не принимал. Но мы хотим, чтобы этот делегат принимал, то есть он первый аргумент, это означает, что он будет возвращать, второй аргумент означает,
15:47
Speaker A
что он будет принимать и третье тоже. То есть вот после первого аргумента уже идут а параметры, которые мы хотим видеть в методе вот, ну, которые мы хотим передавать. Если мы тут укажем funй вот так вот напишем три инта, это
16:00
Speaker A
означает, что это будет метод, который должен будет вернуть intнимать два параметра. То есть это делегат materation мы можем теперь стереть и посмотреть на наш код. И здесь ничего не поменяется. Мы точно также можем сюда передавать делегаты, только уже мы
16:17
Speaker A
увидим, что тип у нас будет. Ну, потому что они просто сигнатуры эти схожи. И на самом деле, если, ну, мы можем здесь создавать тоже вот этот делегатф следующим образом. Мы можем, допустим, сказать, вот есть у нас такая операция, вот это вот взять, скопировать
16:34
Speaker A
наш нашу анонимную функцию, которую мы сделали с помощью лямбда выражения, и сюда её просто передать. То есть мы таким способом быстро создали шаблонный делегат, который мы сюда просто передаём. Также мне вот Rider советует, что мы можем его преобразовать в local
16:50
Speaker A
function. То есть мы можем сделать локальный метод и также, ну, то есть это уже просто обычный метод, который мы просто сюда передаём. И он также будет подходить под эту вот сигнатуру вот этого шаблонного делегата, а, который мы здесь используем. То есть вместо того,
17:06
Speaker A
чтобы создавать свои, мы можем использовать шаблоны. И чаще всего используются именно шаблоны, ну, что просто не городить свои. Вот. И таких шаблонных делегатов их несколько. Это, э, и pricate. Отличаются они сигнатурами. Fun он должен что-то возвращать обязательно. Action он ничего
17:25
Speaker A
не возвращает, он просто делает какое-то действие. А предикей он должен обязательно возвращать бул. Вот. И мы сейчас посмотрим разные примеры, как с ними работать. Давайте рассмотрим следующий пример. Предположим, у нас есть модель класс US. У него есть несколько свойств, и нам нужен какой-то
17:41
Speaker A
класс, который будет выполнять различные операции с юзером. Ну, например, user processor. Весь этот класс построен на том, что у него есть несколько методов, каждый из которых принимает список юзеров, и он выполняет какую-то операцию с этим списком. Предположим, есть метод,
17:58
Speaker A
который send emails, отправляет там welcome имейлы, есть метод, который деактивирует юзеров, есть метод, который просто отчёт какой-то печатает. И здесь просто в каждом методе я с помощью цикла for reach перебираю каждого юзера и выполняю какое-то действие. Ничего не
18:14
Speaker A
возвращаю, просто выполняю какое-то действие. То же самое и здесь. Я обращаюсь к свойству, ну, то есть к каждому юзеру, я выставляю из activate false. Я деактивирую их. То же самое здесь. Я, допустим, печатаю какой-то отчёт для каждого юзера. И какой минус у
18:29
Speaker A
этого класса? Во-первых, тут очень много шаблонного кода, который повторяется. То есть мы везде вызываем один и тот же цикл. И этот класс, у него ещё и ответственность огромная. То есть он и отправляет письма, и он деактивирует пользователей, и так далее. Это является
18:43
Speaker A
очень плохим примером. Так делать не нужно. Вот как можно сделать, например, по-другому с помощью делегатов? Мы берём и вот это вот действие, мы его как бы инкапсулируем. Мы говорим, что есть какой-то делегат user action, и это будет просто действие какое-то. И мы
19:01
Speaker A
теперь имеем в этом good user processor, уже вот в этом классе user processor один только метод process users, который принимает список юзеров и делегат, который, ну, то есть и принимает действие, которое нужно сделать со всеми этими юзерами. И на самом деле здесь мы
19:18
Speaker A
можем принимать как и наш user action, вот этот следующий, потому что, ну, это наш делегат, мы его принимаем. Так, мы можем принимать и шаблонный делегат экшн. То есть я уже говорил о нём, да, есть у нас экшн. И в отличие от фанка,
19:35
Speaker A
он имеет только параметры, которые, ну, приходящие, которые только принимает. Он ничего не не возвращает. То есть у него всегда тип, а, возврата - это void.
19:45
Speaker A
Поэтому мы можем здесь принимать какие-то параметры. И здесь мы работаем именно с юзером. То есть этот делегат принимает только юзера. Вот мы можем указать либо action, либо можем передать user action, как хотите, это неважно.
19:57
Speaker A
Можно использовать, давай, давайте будем использовать экшн. То есть я вот этот user action закомментирую, и я просто пробегаюсь. То есть у меня есть теперь уже один метод, одна ответственность. Я просто хочу обработать юзеров. И для каждого юзера в методе for each я
20:11
Speaker A
вызываю вот этот делегат и кладу сюда юзера. Вот. И где же мы будем решать, что мы будем делать с юзером? Правильно, мы будем извне это делать. То есть мы сейчас в классе Program покажу вам пример. Вот я создаю список юзеров лист,
20:26
Speaker A
создаю процессор, который будет выполнять операции, и у процессора вызываю метод process users. Первый параметр я принимаю юзеров, а вторым параметром я должен принимать уже экшн.
20:39
Speaker A
То есть я должен принимать делегат, по сути метод, то есть действия, что я должен сделать со всеми этими юзерами.
20:45
Speaker A
И, допустим, отправка писем у меня будет выглядеть следующим образом. Я просто вывожу там, ну, условно, я тут делаю какую-то операцию. Я могу тут вызвать какой-то сервис и так далее, это неважно. Я тут что угодно могу сделать.
20:56
Speaker A
Главное, чтобы сигнатура соответствовала. То есть я могу взять и выделить вот этот вот этот локальный метод, то есть анонимный локальный метод.
21:06
Speaker A
Я могу взять и вынести, допустим, вот этот анонимное выражение с помощью лямбда выражения в локальную функцию. И у меня, предположим, есть какой-то метод. Он может быть в другом классе, он откуда угодно может быть, он может прямо тут лежать, который что-то делает.
21:21
Speaker A
Допустим, send emails, у меня называется метод, и я просто кладу, а, получается, в процессор мой юзеров и вызываю для каждого юзера метод sent emails. То есть он у меня принимает usер и тут делает какое-то действие. То есть вот так вот
21:37
Speaker A
удобно на самом деле мы это можем сделать. То есть у меня будет тут уже набор операций, и я решаю, какие мне операции нужно сделать. То есть если мне нужно будет добавить новую операцию, допустим, вот то же самое. активация
21:47
Speaker A
юзеров, да, отчёт юзеров. И я захотел добавить новый метод, новое действие, допустим, архив юзеров. Ну, сделать архивацию юзеров. И мне для этого не надо идти в мой бетпроцессор, делать тут, копировать так новый метод, вызывать тут архив usеer и так далее. Я
22:06
Speaker A
вместо этого операцию по архивации могу сделать здесь, да, я могу, допустим, взять откуда-то из другого места этот метод, то есть просто вынести это в локальный метод.
22:16
Speaker A
Здесь, допустим, будет архив usеer и всё. И вызвать просто передать его как делегат. То есть передать метод делегат за, ну, он запомнит, что о'кей, теперь я ссылаюсь на этот метод и этот метод я вызову, когда ты мне скажешь. И вот
22:31
Speaker A
здесь я говорю вызывать его. Можно опять же сделать это с помощью метода inv, а можно и так. У нас делегат ещё может быть наable. Если он наable, то он начнёт ругаться и говорить типа: "Ну, сделай проверку". Можно, конечно,
22:44
Speaker A
сделать проверку следующим образом, если деликат не равен ал, но можно эту делать проверку более удобно. То есть с помощью синтактического сахара мы можем вызвать с помощью инвоука, но здесь мы можем поставить ещё и знак вопроса, да? То есть этот invoke, то
23:01
Speaker A
есть этот метод внутри делегата вызовет только тогда, когда он не будет на то есть если он будет нал, он просто не вызовется. То есть вот вот так вот в одну строчку это можно, в принципе, записывать. Итак, следующий метод уже с
23:12
Speaker A
предикатом. То есть мы посмотрели Fun, мы посмотрели Action. Давайте рассмотрим Predicate. Смотрите, у меня есть, предположим, класс B numberfinder. Этот класс должен искать числа в каком-то списке. То есть, предположим, он у меня принимает список чисел и называется find
23:31
Speaker A
numbers. То есть он ищет все чётные числа. Что мы тут делаем? Мы тут формируем пустой список, пробегаемся фручом по каждому элементу, говорим, если у нас остаток равен ноль, то мы добавляем в этот список наше число и возвращаем. Ну, по сути, мы ищем все
23:45
Speaker A
чётные числа в нашем numberре. О'кей? Хотим дополнить какие-то ещё операции сделать. Допустим, найти нечётные числа, потом найти числа, которые больше десяти, то есть, ну, класс, который вообще, который работает с числами. И получается, опять у нас слишком много тут методов появляется. Каждый раз у нас
24:03
Speaker A
всё примерно по одному шаблону происходит. Как это можно улучшить? Как вы уже догадались, можно сделать good numberferinder. И можно сделать один метод, который просто применит правила для всей нашей, то есть он применит фильтр для всего нашего списка. Как мы
24:19
Speaker A
это сделаем? У нас есть один метод Fine numbers. Мы принимаем список чисел и принимаем delлегат, называем его фильтр.
24:27
Speaker A
А по аналогии, как это может выглядеть? Мы можем сделать тут свой делегат на он должен обязательно возвращать бул, потому что сейчас объясню почему. И он будет называться, предположим, предиATE.
24:41
Speaker A
Вот таким образом. И он будет ещё принимать число, потому что мы работаем с числами. И, допустим, у нас условия там вот чётное, нечётное, больше десяти, меньше десяти, остаток отделений и так далее. То есть мы с помощью этого делегата будем сейчас задавать различные
24:58
Speaker A
условия для нашей коллекции. Предигат - это вообще утверждение. Переводится, ну, придики как утверждение. Поэтому мы и возвращаем здесь бул. То есть мы, а, возвращаем какое-то утверждение верное или неверное. Так вот, мы можем принимать здесь свой предит. Мы можем
25:14
Speaker A
это назвать, кстати, предиate, какое-то утверждение. И смотрите, где мы применяем этот предикат. Применяем мы его в этом месте. Сначала мы точно так же, как и здесь, создаём временную коллекцию. Потом мы форычом тоже пробегаемся по всем числам. Но условие,
25:28
Speaker A
которое каждый раз вот здесь вот разное, то есть здесь у нас остаток отделения, здесь у нас больше, да, какое-то неравенство, мы его применяем это условие здесь. То есть, так как наш делегат возвращает буll, мы можем в if его поместить, потому что
25:46
Speaker A
здесь у нас вернётся бул. по результату вот этого метода, который сюда мы положим, когда мы его вызовем вот этим, ну, вот так вот, да, prate, положим сюда number, он вернёт бу там равно равно true, условно, да. Вот. И если у нас вот
26:01
Speaker A
это условие, которое мы сюда положим, будет true, то у нас мы в коллекцию положим новый элемент. То есть это, по сути, фильтрацию. И эту фильтрацию мы уже задаём здесь сами. Как это происходит? Мы создаём список чисел, создаём наш finder, предположим, good
26:17
Speaker A
number finder, и у finder вызываем метод find numbers. Передаём список наших чисел. И вот здесь вот указываем условия. Как это условие должно выглядеть? Это, по сути, сейчас анонимный метод с помощью лямбда выражения. Если у нас нам де, ну, если у
26:34
Speaker A
нас остаток отделения равен нулю, то мы, ну, возвращаем тру. Ну, по сути, смотрите, если мы вынесем это в local function, это будет просто метод, который возвращает буllй просто возвращает остаток отделения от нуля.
26:48
Speaker A
Только не число, а именно выражение, то есть булевое выражение. Если делится на ноль, то есть если остаток отделения ноль вернёт trueu если нет, false. Вот супер в коротком виде мы это можем записать вот так вот следующим образом.
27:00
Speaker A
То есть это очень удобно. То есть мы теперь с помощью одного нашего метода можем любые операции с числами, любые условия, то есть для вот этого фильтра, для поиска чисел, мы можем задавать вот тут в делегате и передавать его через
27:13
Speaker A
делегат. И это может вам напомнить то, как устроеню. Потому что если вы пользовались Linkю, то там очень схожий механизм. Как бы это выглядело бы, если бы мы писали эту фильтрацию с Link? Мы бы обратились просто сразу к Numbers. Мы
27:28
Speaker A
бы вызвали тут метод where, мы бы не принимали уже number, а просто бы работали с нам и всё. И получается. А почему это так работает? А на самом деле потому, что внутри, ну, под капотом Link вот эти все методы where там, а, find,
27:45
Speaker A
вообще любые методы, там группировки и так далее, они все принимают делегаты. Они все принимают делегат, только здесь они принимают ан, а не предиate, а fun.
27:55
Speaker A
Ну, потому что они ещё и возвращают значение. То есть, если мы перейдём where, как он реализован, то мы сейчас это увидим. И по сути весь линк, то есть все его методы, они основаны на вот этих делегатах. То есть это уже то, да, что
28:11
Speaker A
везде вы повседневно используете. Если вы пишете, может быть, запросы, ещё что-нибудь, работаете с коллекциями, вы по-любому используете Linkю. И здесь вот как этот механизм работает, что здесь мы пишем нам и получаем доступ типа к нам, можем что-то с ним делать. Вот как
28:26
Speaker A
раз-таки это сделано с помощью делегатов. Он прогоняется по всем элементам и просто применяет вот этот делегат к этому элементу. Вот какое-то условие, которое мы задаём здесь. Вот так вот, в принципе, и работает lиink.
28:39
Speaker A
То есть теперь вы это тоже понимаете. Также мы можем использовать делегаты как колбк. Вот если вы писали код на джавакрипте, то вам это должно быть знакомо. Условно у нас есть какой-то датапроцессор, допустим, какой-то класс, который выполняет достаточно длительную
28:54
Speaker A
операцию. И нам нужно следить за прогрессом выполнения этого класса, потому что он условно там в цикле делает какие-то операции, и мы как-то можем получить, ну, сколько процентов, сколько он сделал уже этой операции. Вот как нам это сделать? Мы создаём делегат, который
29:11
Speaker A
нам ничего не будет возвращать. он будет только принимать какое-то, ну, число percent complete, да? То есть он будет принимать только, а сколько процентов завершено в нашем классе дата процессор этот делегат принимаем в конструкторе.
29:27
Speaker A
Сейчас расскажу для чего. То есть мы уже принимаем тут делегат не в методе, а в конструкторе при создании этого класса.
29:33
Speaker A
И дальше, когда мы вызываем метод про создато, то есть метод по обработке данных, там в цикле какая-то длительная операция происходит. Дальше, если у нас там есть остаток отделения не равен нулю, мы идём дальше. Ну, чтобы процент нормально вычислялся. Вычисляем процент
29:49
Speaker A
выполненный, там, сколько у нас выполнилось. И дальше вызываем делегат и кладём сюда этот процент. А где у нас делегат? А делегат у нас получен из конструктора вот здесь вот. Да. И можно, конечно, его здесь принимать, можно в конструкторе, но мы вызываем делегат. То
30:07
Speaker A
есть мы вызываем этот метод, который мы, ну, с, и кладём туда наш процент. И где вызовется этот метод? Мы его просто тут вызываем. А где он вызовется? Сейчас мы посмотрим. Вот. И в конце, ну, когда у нас весь цикл прошёл, мы на всякий
30:22
Speaker A
случай говорим, что у нас там всё, 100% выполнено. Вот. И посмотрим, где мы используем этот метод. Используем мы его здесь. То есть мы здесь создаём новый экземпляр dataпроцессор и кладём сюда метод. То есть мы кладём ссылку на метод, то есть мы сюда делегат кладём.
30:37
Speaker A
Что из себя представляет этот делегат? Вот его сигнатура, она соответствует, то есть это баррепортер. Мы сюда принимаем процент и работаем с этим процентом, с этим числом мы уже здесь. То есть мы не внутри дата процессора с ними работаем,
30:54
Speaker A
а вот здесь вот работаем, а в месте, где мы вызываем этот код. То есть мы сдвигаем там курсор в консоли, мы там сейчас бары будем отрисовывать. В общем, отрисовываем Progress бар, исходя из этого процента. Вот. И давайте посмотрим, как это работает сначала. То
31:11
Speaker A
есть я запущу этот код, и мы увидим, что здесь, да, у нас видно, что столько-то процентов выполнено, там 20, 90, всё, 100 финиш. Вот. То есть мы увидели, что у нас это работает. То есть progrгess ball заполняется. Давайте ещё раз. Вот 0
31:26
Speaker A
10 20 30. О'кей, всё работает. Но как же это работает? Ещё раз, кто не понял, мы кладём сюда метод, который отрабатывает вот в этом месте, да, но вызывается этот метод внутри этого класса, внутри метода прогрес просто processта. Поэтому это
31:43
Speaker A
называется колбком. А колбк типа мы обратно возвращаем выполнение этого метода, условно, да, то есть, ну, из перевода, если смотреть, то есть обратный вызов. Почему обратный вызов? Потому что вот эта делегата вызывается внутри этого метода. Вот. А сам метод выполняется здесь, то есть
32:01
Speaker A
обратный вызов. То есть мы передаём этот метод. То есть мы передаём ссылку на этот метод внутрь датапроцессора. Там внутри где-то он вызывает, то есть с помощью делегата, а вот тут хорошо видна именно суть делегатов. То есть мы м он
32:18
Speaker A
хранит просто вот этот репортер, он хранит ссылку на метод. Он вызывает этот метод, но он вызывается не прямо здесь, а он вызывается вот в этом месте, где этот метод и находится. Вот. То есть мы вызываем этот метод и тут делаем
32:30
Speaker A
какие-то операции. То есть это можно использовать как callback. Этот метод можно прямо сюда, в принципе, вот так вот записать. То есть cent вот в Javaрипте это синтезис тоже довольно популярный. То есть C#ARP - это не так часто используется. То есть это в VPF
32:44
Speaker A
там в приложении с U можно часто использоваться, но тоже иногда бывает. То есть вот можно так, в принципе, это использовать. То есть мы сюда кладём вот этот кулбк. То есть мы кладём этот анонимный метод, который вызовет здесь, да? А вызываем мы его вот тут внутри
32:59
Speaker A
этого метода. Всё. Я думаю, это довольно понятно. То есть я уже кучу раз это повторил. А тоже вот так вот мы можем кулбэки с помощью кулбэков а делать вызов делегатов и тоже с этим работать.
33:10
Speaker A
Ну что ж, а теперь давайте перейдём к веб приложениям, вот кcore я вам покажу сейчас здесь, где мы используем эти делегаты. И на самом деле они используются здесь везде.
33:24
Speaker A
предположим, тот же minimal app, то есть мы видим map get. О'кей, у нас есть какой-то метод get. Что это такое minimal app? Если мы посмотрим на сигнатуру этого метода, то мы увидим, что здесь он принимает делегат. И здесь
33:37
Speaker A
он принимает делегат. То есть либо это request делегат, либо просто делегат. Вот почему здесь принимается делегат. Ну вот так они решили это упростить. То есть мы теперь здесь определяем функционал, который передаётся внутрь.
33:50
Speaker A
Он там внутри с помощью рефлексии. Вот это delegate. Кстати, что это за тип такой delegate? А делегеate на самом деле - это тип, то есть это класс. И любой делегат, он будет являться делегейтом. То есть любой делегат, он
34:03
Speaker A
этот класс, можно сказать, наследует, то есть который мы создаём. То есть это то же самое, что любой объект наследует у нас класс объект object в cшаarпе. Вот так.
34:12
Speaker A
И тут любой делегат, он исследует класс delegate. Вот. И а значит, можно, да, можно сказать, чтобы метод принимал просто delate. И дальше он там с помощью рефлексии как-то определяет параметры, которые мы сюда вводим, потому что мы сюда можем, допустим, from query
34:29
Speaker A
какие-то параметры указывать и так далее. Он их должен как-то распарсить. Вот он это делает. То есть поэтому мы тут принимаем абсолютно любой делегат без какой-либо конкретной сигнатуры.
34:38
Speaker A
Также мы можем принять request delegate. То есть, если мы на самом деле здесь напишем use, вызовем, ну, наш midle, то мы увидим, какая тут будет сигнатура. И мы увидим, что midleвейры тоже принимают делегаты. И принимает он делегат fun, то
34:53
Speaker A
есть он принимает параметр request delegate и возвращает request delegate. Также и здесь, да, можно принимать HTTP контекст. То есть мы увидим, что все midleвейры построены на делегатах, minimum апи построены на делегатах. Вот здесь, допустим, я показываю пример, где
35:10
Speaker A
идёт, ну, он принимает вот этот minimal app именно request delegate. Вот что такое request delegate? Давайте посмотрим на этот метод. Вот мы видим, что тут он принимает request delegate.
35:21
Speaker A
Он передаёт его дальше в метод maps. Ну, какой-то mapпинг происходит. И request delegate - это вот просто delegat. В отдельном классе лежит requestdelegate.cs.
35:33
Speaker A
А он возвращает просто task и принимает http контекст. То есть вот такая вот сигнатурка. И мы вот с этим контекстом можем здесь как-то теперь работать. То есть мы принимаем делегат, вот передаём по сути вот это. Это просто анонимный
35:47
Speaker A
метод по сути, да, а с помощью лямда выражения, который мы сделали. В принципе, его можно было бы и так сделать, на самом деле, но, в общем, сделали мы его с помощью анонимного выражения. Здесь работаем как-то с нашим контекстом, что-то выполняем, какой-то
36:00
Speaker A
результат, таск возвращаем, и он уже внутри всё это мапит и выполняет этот делегат, как ему нужно. То есть таким образом он скрыл вот те сложные операции, которые он выполняет внутри, а наружу нам дал просто положи делегат, какой-то метод, что-то, короче, сделай,
36:18
Speaker A
а я внутри уже определю, как это будет работать конкретно. И ещё делегаты активно используются в dependency injection либо в каких-то конфигурациях.
36:27
Speaker A
Предположим, у нас есть метод. Если вы пользовались а DB контекстом, то вы его по-любому регистрировали. И здесь вы можете вызвать метод addbx. Ну, предположим, там базовый DB контекст мы регистрируем и посмотрим, что принимает этот метод. Делегат. Он принимает снова
36:45
Speaker A
делегат action. Вот. И какие-то опции. Вот для чего это делается. Мы можем тут вызвать, обратиться к этим опциям и как-то их настроить. у опции мы можем получить свойства, мы можем вызвать какие-то методы. То есть это делается здесь для того, чтобы мы применили
37:03
Speaker A
какое-то действие к каким-то классам, условно. То есть у нас есть опции класс, и мы к ним хотим применить какие-то действия. И эти действия мы описываем здесь. Ну, допустим, вот, не знаю, use seeding. Вот мы применяем вот это действие здесь, но оно применяется не
37:22
Speaker A
сразу. Это делается в конфигурации. И я давайте вот сейчас покажу вам, как сделать по аналогии свой. Ну, допустим, вы делаете свой DB контекст. О'кей, вы сделали database сервис, и у этого сервиса есть опции, а, есть различные опции, которые потом
37:40
Speaker A
используются в методах. Там, допустим, строка подключения, а, тайoutу какой-нибудь. Очень много опций можно сделать по настройке для работы с базой данных. И эти опции вы хотите принимать в конструкторе, правильно? И получается вам, ну, когда вы регистрируете это в
37:56
Speaker A
Dependy Injection, вам нужно эти опции как-то настроить. Как это можно сделать с помощью делегатов? Вот, во-первых, мы создаём класс Database Service Options.
38:05
Speaker A
Просто набор идёт опций. И как мы эти опции будем настраивать? Можно сделать по аналогии с DB контекстом и воспользоваться паттерном Builder. А, ну, как это работает? То есть мы здесь обращаемся к options и в в роли Options здесь выступает наш DBEX options
38:22
Speaker A
builder. Видим, да? То есть это не сами опции, а это именно builder. И внутри билдера уже лежит свойство options там, ну, которые мы можем либо изменить, хотя здесь options, видите, он имеет только get, то есть сетера у него нет. И любое
38:36
Speaker A
изменение опции вызывается через методы, допустим, configure warnings, так, add interceptors и так далее. То есть мы можем здесь настроить dbтек с помощью наших методов. Вот как сделать по аналогии? Хорошо, мы, допустим, добавили наш databйсевиice, и мы хотим вот эти
38:53
Speaker A
опции, перед тем, как их вложить сюда в конструктор, как-то сконфигурировать. Для этого мы тоже сделаем builder. И в этом билдере мы тоже имеем наши опции.
39:02
Speaker A
Они тут создаются пустые изначально. И мы просто пишем набор разных методов. То есть это паттерн, он очень простой. У нас есть разные методы, которые возвращают каждый раз наш builderр. То есть мы условно используем метод, пишем метод users connection string, принимаем
39:21
Speaker A
наш connection string. В этом методе мы в опциях устанавливаем этот connection string и возвращаем this. Возвращаем, то есть тот же, ну, этот же экземпляр.
39:31
Speaker A
Только в этом экземпляре этого класса у нас уже будет как бы свойство Connection string заполнено. Вот то же самое со всеми остальными методами. И потом там, где мы используем этот билдер, мы можем друг за другом вызывать эти методы у
39:47
Speaker A
одного и того же экземпляра. И получается, мы таким образом конфигурируем вот эти опции. И также я сделал просто тоже свойство options, доступное только для чтения. Как это теперь нам регистрировать? То есть, если мы посмотрим, я сделал здесь метод
40:01
Speaker A
расширения. Database service - это мой метод расширения, который в DI регистрирует как раз-таки мой DB контекст, условный, мой личный. И здесь он принимает теперь тоже делегат. Вот здесь вот я принимаю э вот этот builderр. И с помощью этого
40:19
Speaker A
билдера я вызываю различные методы, которые конфигурируют опции. Как я это сделал? Давайте посмотрим. Я сделал класс extension статический. Вот. То есть я расширяю, а мой builder, то есть я расширяю i service collection, дополнительные методы для регистрации в Ji. И здесь я принимаю э здесь, в этом
40:39
Speaker A
делегате принимаю. Принимаю я здесь database options builder. То есть я буду работать с builderдером. Configure builder. То есть я здесь принимаю ссылку на метод. И в этом методе я взаимодействую с configдером, через который я сконфигурировал мои опции. Да.
40:57
Speaker A
Дальше я добавляю в мой dependции, чтобы я мог их использовать в database сервисе. Ну, чтобы они сюда в DI попали.
41:08
Speaker A
Мне нужно их зарегать в singleton. Вот. То есть мне нужно их зарегать, чтобы они туда попали, чтобы он их получил через Dependcy Injection. У меня, кстати, есть на канале видео про Decy Injection. И здесь дальше, после того, как я создал
41:21
Speaker A
новый экземпляр билдера, я просто вызываю мой делегат configure builder и кладу сюда этого билдера. То есть мы сейчас посмотрим, как это через вызов происходит. И в конце я просто возвращаю тут options. То есть, ну, я добавляю в singleton. И, кстати, метод регистрации
41:38
Speaker A
в DILON тоже принимает делегата. Он принимает, а, где мы имеем доступ к сервис провайдеру. То есть мы можем здесь там получить через сервис провайдеer другие какие-то SDI моменты, а, ну, которые зарегистрированы. Ну, а здесь я просто возвращаю, а, мои опции.
41:54
Speaker A
То есть я регистрирую в DI здесь конкретно опции, и здесь я их возвращаю. То есть я с помощью билдера просто конфигурирую эти опции вот здесь вот и просто их возвращаю, то есть добавляю в dependence injection. И дальше я просто
42:07
Speaker A
регистрирую мой databйсевис через cop. И когда мы его будем использовать, сюда эти опции попадут уже сконфигурированные. А где мы их конфигурируем? Правильно, мы конфигурируем вот в этом месте в методе databй севис в моём методе расширения. Я здесь с помощью делегата получаю доступ
42:25
Speaker A
к на к моему билдеру, да, потому что я здесь по сути сюда кладу метод. То есть я могу это to local function сделать. То есть у меня есть метод builder, который принимает в параметрах вот этот builder configure, да, который называется. Здесь
42:43
Speaker A
я как-то конфигурирую эти опции. То есть на самом деле можно было сделать без билдера, можно было тут принимать опции и сразу там options точкой и так далее и конфигурировать их конкретно. Вот. И этот просто метод я кладу сюда. То есть
42:58
Speaker A
конфигурацию я пишу здесь, а применяется конфигурация уже внутри. То есть это опять же только благодаря делегатам доступно. Вот. И таких примеров тут полно. Предположим, метод configure, да, благодаря которому мы конфигурируем там с помощью паттерна Iptions. Мы можем конфигурировать разные, ну, штуки.
43:18
Speaker A
Допустим, я хочу сконфигурировать host options, да? И здесь мы увидим, что он принимает опять же делегат, там options.
43:27
Speaker A
Один из вариантов. мы можем принять options. Теперь я могу обратиться к этим опциям и вот так вот напрямую просто взять и изменить опции. Допустим, сказать, что у меня теперь а сервисы стартуют неконкурентно. Вот. И это повлияет на приложение. То есть мы
43:43
Speaker A
видим, что конфигур тоже внутри себя использует делегат, внутри которого он его применяет. То есть он просто кладёт уже и там внутри дальше к этим опциям, где, ну, где-то вызовется этот делегат, и вот эти опции сконфигурируются. То есть вот этот метод мой вызовет где-то.
44:00
Speaker A
И вот это важно понимать. То есть по сути вы везде используете дельгаты. И вы можете использовать делегаты теперь в своём коде. То есть какие-то использовать паттерны, где-то это их применять и улучшать свой код. Давайте я покажу вам пример из того, что мы делали
44:13
Speaker A
когда-то на моём курсе вместе с ребятами. Предположим, вот валидация кастомный валидатор, то есть кастомный метод расширения must be val. Мы здесь видим, что этот метод расширения принимает фанк, принимает делегат, и он работает там с каким-то элементом, и он
44:29
Speaker A
возвращает, то есть принимает фабричный метод. То есть он возвращает какой-то элемент и принимает фабричный метод result. И дальше здесь я этот result, вызываю этот фабричный метод и удобно его использую. Дальше я это делаю для а fluid validation, то есть для того,
44:47
Speaker A
чтобы я мог фабричный метод передавать вот здесь вот. То есть это было тоже на канале, это мы и на курсе делали. Есть ещё один пример с кэшированием.
44:55
Speaker A
Допустим, вы пишете класс сервис по работе с кэшем, и вы хотите реализовать паттерн, то есть вы хотите удобно сделать метод get or seting, который будет принимать тоже некую фабрику. То есть вы здесь принимаете некие метод. То есть здесь, смотрите, я принимаю
45:11
Speaker A
делегат, который вернёт task, то есть какую-то операцию любую. Вот factory. И этот метод он будет у меня на получение данных. То есть я сначала пытаюсь прочитать из кэша какие-то данные. Если у меня этого сделать не получается, то у
45:27
Speaker A
меня кэш пустой, и мне нужно получить мои данные. Вот. И эти данные я получаю с помощью вот этого метода A Factory. А Factory - это мой делегат. То есть вот этот вызов этого метода, сам метод, он будет где-то выше. Вот. И здесь я его
45:43
Speaker A
просто вызываю. Я эти значения получаю и передаю дальше и сохраняю их в кэш. Вот пример, как это может работать. То есть вот у меня есть класс тест какой-то, я хочу получить какие-то данные. И вот здесь вот я к это, ну, вместо этого
45:58
Speaker A
делегата я сюда кладу как раз-таки метод, ну, то есть вызов для получения моих данных. То есть и уже вот с этими данными дальше внутри вот этот класс для кэширования будет работать. А, то есть я это делаю для того, чтобы можно было
46:11
Speaker A
просто удобно работать с этим классом. Ну что ж, я думаю, я достаточно рассказал про делегаты. Теперь вы можете попробовать их использовать на практике.
46:19
Speaker A
Всем спасибо за просмотр, ставьте лайки и всем пока.
Topics:делегатыC#Asp Net CoreпрограммированиеООПgeneric делегатыконфигурацияссылки на методывеб-разработкасобеседование

Frequently Asked Questions

Что такое делегаты в C# и зачем они нужны?

Делегаты в C# — это тип, который представляет ссылку на метод с определённой сигнатурой. Они позволяют передавать методы как параметры, что повышает гибкость и расширяемость кода.

Как делегаты помогают улучшить дизайн приложения?

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

Какие стандартные делегаты существуют в C# и когда их использовать?

В C# есть стандартные generic делегаты, такие как Func и Action, которые упрощают работу с методами, принимающими параметры и возвращающими значения. Их удобно использовать вместо создания собственных делегатов.

Get More with the Söz AI App

Transcribe recordings, audio files, and YouTube videos — with AI summaries, speaker detection, and unlimited transcriptions.

Or transcribe another YouTube video here →