Иногда это помогает мне упростить концепции, ссылаясь на знакомые концепции.
Представьте себе делегата как контейнер (см. Изображение ниже):
A функция = деревянный блок, который помещается внутри этого контейнера.
Мы не можем передавать функции напрямую, например, в качестве параметров, но мы можем передавать делегатов! Таким образом, в основном мы помещаем деревянный блок (функцию) в контейнер (делегат) и можем теперь передать его в качестве параметра и использовать его, когда нам нужно.
Подпись = крышка. Это гарантирует, что мы можем поместить в контейнер только блок правильной формы.
Вызов делегата = взятие всех блоков (функций) в контейнере и «вызов» или «вызов» этих функций.
многоадресный делегат - это когда мы помещаем более 1 блока в контейнер (поэтому, когда мы вызываем многоадресный делегат, все функции внутри будут вызываться).
Событие будет просто контейнером (делегатом) с блокировкой. Это препятствует тому, чтобы кто-то открыл крышку, выливая все блоки внутри.
Эти абстракции взяты из моего блога, если вы хотите прочитать более подробно
Простое объяснение делегатам и мероприятиям
Кроме того, как только делегаты и события имеют смысл, стоило бы взглянуть на эволюцию делегата , чтобы понять, как делегаты эволюционировали в лямбда-функции.
Надеюсь, эта абстракция поможет лучше понять делегатов, она, безусловно, помогла мне.