Надеюсь, вы понимаете, что переменная типа string похожа на контейнер, содержащий строку символов, и вы можете посмотреть на них по отдельности, передать их как коллекцию и т. Д. Это довольно легко визуализировать, поскольку эта переменная контейнер, в котором хранятся данные, потому что мы постоянно храним данные в реальном мире; кусочки бумаги в коробке / файле и т. д.
Делегаты подобны переменным для методов - и это гораздо сложнее понять, что мы можем передать метод, как если бы он был просто как данные, и мы можем заставить компьютер запустить метод .. но это то, что делегат. Когда вы объявляете делегата, это как когда вы объявляете свой собственный класс:
delegate void SomeMethod(); //specify a delegate
class Person{ //specify a class
string FirstName;
string LastName;
}
Точно так же, как когда вы создаете класс, вы даете себе возможность создать экземпляр этого класса, когда вы объявляете делегата, вы даете себе возможность создать экземпляр этого делегата. Ваш экземпляр класса ссылается на данные, например, здесь имя и фамилия человека. Экземпляр делегата ссылается на метод, а не на данные. Вы можете создать один экземпляр класса, который ссылается на «Джона» и «Смита». Вы можете создать экземпляр делегата, который ссылается на Method1 (). Вы можете создать другой экземпляр класса, который ссылается на «Билл», «Джонс». Вы можете создать другой экземпляр делегата, который ссылается на Method2 ().
Вы можете связать любой метод с вашим экземпляром делегата, если метод имеет сигнатуру, равную делегату. Этот делегат выше примет ссылку на любой метод, который не принимает параметров и возвращает void. Если у вас есть один или несколько таких методов, вы можете присоединить их к экземпляру делегата, передать экземпляр делегата как переменную, и вещь, которой вы передали делегат, может вызывать методы без необходимости знать как называется метод или что-то в этом роде.
Зачем нам это делать? Одно из основных применений делегатов - обработка событий. Microsoft создала элементы управления пользовательским интерфейсом, которые способны что-то делать - кнопки, на которые вы можете нажимать. Вы захотите, чтобы ваша кнопка что-то делала при нажатии, но все в мире захотят, чтобы при нажатии ее кнопка делала что-то другое, поэтому Microsoft не может написать код для этого. Однако они могут сказать, что сделают кнопку, которая принимает делегата (метод, переданный как переменную), и кнопка обещает вызвать метод при нажатии. Вы предоставляете кнопке код, который делает то, что вы хотите, как делегат. Ваш метод должен иметь определенную подпись (аргументы), потому что кнопка хочет передать вашему методу некоторые данные, которые могут быть вам полезны; возможно, местоположение мыши при появлении часов или число нажатий на них. Компоненты пользовательского интерфейса имеют сотни различных видов событий, все они работают на делегатах
Еще один хороший пример делегатов - в старом стиле асинхронного программирования, когда у нас были пары методов Begin / End. Вызов Begin обычно запускал бы новый поток, делая что-то, и мы должны были бы предоставить метод (наш метод) для если метод Microsoft Begin завершит выполнение чего-либо, он вызовет наш метод, чтобы сообщить нам об этом. Обычно тогда наш код вызывает End, передавая некоторую ссылку, которую дал наш метод, и мы получаем результат. Например, отправка запроса на сервер может занять некоторое время, поэтому мы начнем его, перейдем к другим действиям, и когда ответ будет готов, наш делегат получит уведомление о вызове и обработает результат
Итак, привыкните к понятию, что делегат - это просто способ или ссылка на метод, вы передаете его, то, что вы передаете ему, может запустить его и предоставить ему данные, не имея представления о том, что он делает.В терминологии это также называется обратным вызовом - вещь, которая будет вызываться, когда внешний метод завершит свою работу, хотя это довольно свободный термин - его можно использовать для ссылки на ваш метод, который выполняет работу, илиэкземпляр делегата, указывающий на ваш метод, предмет, который передается. Фактически, они эквивалентны в зависимости от контекста диалога.
Сам делегат больше похож на коллекцию / массив - вы можете прикрепить несколькометоды к нему и при вызове делегата все они будут работать, но не в каком-либо определенном порядке.В вашем примере вы присвоили ему только один, но это может быть несколько:
SomeMethod delegs = null;
delegs += new SomeMethod(MyMethod1);
delegs += new SomeMethod(MyMethod2);
Вызов этого делегата вызовет запуск MyMethod1 и MyMethod2, возможно, в 2,1 порядке
События также являются делегатами, но это немного особый случай, о котором мы говорили выше с помощью обработчика нажатия кнопки.Когда делегат указан с ключевым словом события, он может быть вызван только внутри класса, который объявил переменную делегата.Элементы управления пользовательского интерфейса используют это, чтобы гарантировать, что только они могут выполнять делегат;Вы не можете получить доступ к кнопке и принудительно запустить ее обработчики часов, потому что список делегатов, который обрабатывает щелчок, объявлен как событие.Если вы хотите, чтобы кнопка программно вызывала список обработчиков событий, вы обычно должны создавать его подклассы, чтобы ваш код стал «внутри» кода кнопки
Слушатель, поскольку фраза чаще ассоциируется с событиями, но это разумносинонимичен с обратным вызовом и обработчиком событий - когда вы добавляете слушателя к событию, вы говорите, что пишете код, который будет обрабатывать возникновение события, ваш код (как обработчик делегата / события), который действует при возникновении события,Это не "слушает" само по себе;он просто зависает и запускается в действие, когда объект, вызывающий событие, вызывает список делегатов / обработчиков событий, связанных с событием.
В стороне, потому что экземпляры делегатов представляют переменную, которая указывает на метод, т.е.они указывают на действие, ваши имена должны быть глаголом, а не существительным.Вы вызвали свой listOfHandlers, но для вашего понимания было бы более полезно вызвать экземпляр делегата после происходящего события / действия.Вариант использования, к которому вы обращались, был чрезмерным, поэтому, возможно, вам следует назвать его CarEngineOverRevving.Вы могли бы иметь другой, когда температура превышает.Если оба этих делегата имеют одинаковую подпись (вы хотите, чтобы люди, которые будут обрабатывать эти события, делали это с помощью метода без аргументов), вы можете повторно использовать один и тот же делегат для разных событий:
public void delegate CarEngineProblemHandler();
public CarEngineProblemHandler CarEngineOverRevving = null;
public CarEngineProblemHandler CarEngineOverheating = null;
Делегатэто ваш способ объявить, как вы хотите, чтобы предоставляемые вам методы выглядели так, как вы хотите.Список именованных проблем - это то, о чем вы заявляете, что другие люди могут обеспечить некоторую обработку.Я мог бы решить не давать вам обработчик для перевыполнения, потому что я никогда этого не сделаю, но в любом случае может произойти перегрев, поэтому я обязательно предоставлю вам обработчик / слушатель / делегат / обратный вызов для вызова этого случая