Подтвердить что ты не робот

Помогите понять делегаты .NET, события и обработчики событий

В последние пару дней я задал пару вопросов о делегатах ЗДЕСЬ и ЗДЕСЬ. Признаюсь... Я действительно не понимаю делегатов. И я ДЕЙСТВИТЕЛЬНО ДЕЙСТВИТЕЛЬНО ДЕЙСТВИТЕЛЬНО хочу понять и освоить их. (Я могу определить их - введите безопасные указатели функций, но поскольку у меня мало опыта работы с языками типа C, это не очень полезно.)

Может ли кто-нибудь рекомендовать некоторые онлайн-ресурсы, которые объяснят делегатов таким образом, который не предполагает ничего?

Это один из тех моментов, когда я подозреваю, что VB действительно меня мешает, потому что он делает некоторые проводки для меня за кулисами.

Идеальный ресурс просто объяснит, что представляют делегаты, не ссылаясь ни на что другое (события и обработчики событий), покажет мне, как все все подключено, объясните (как я только что узнал), что делегаты являются типами и что их делает уникальным как тип (возможно, с использованием магии ildasm)). Затем эта основа расширилась, чтобы объяснить, как делегаты связаны с событиями и обработчиками событий, которые нуждаются в довольно хорошем объяснении там, где они есть. Наконец, этот ресурс мог бы связать все это вместе с использованием реальных примеров и объяснить, что проводка происходит автоматически компилятором, как их использовать и т.д. И, о да, когда вам следует и не следует использовать делегатов, другими словами, недостатки и альтернативы к использованию делегатов.

Что вы говорите? Может ли кто-нибудь из вас указать мне ресурс (ы), который может помочь мне начать мое путешествие к мастерству?

ИЗМЕНИТЬ Одна последняя вещь. Идеальный ресурс объяснит, как вы можете и не можете использовать делегатов в объявлении интерфейса. Это то, что действительно сбило меня с толку.

Спасибо за вашу помощь.

Сет

4b9b3361

Ответ 2

Самое простое объяснение заключается в том, что делегаты позволяют динамически назначать "имя" метода переменной или передавать ее как параметр (вы не назначаете имя строки, это ссылка на сам метод вы присваиваете переменной).

Другой код может выглядеть в переменной и вызывать метод, хранящийся там позже.

Делегат должен иметь определение (например, интерфейс), и для этого вы используете ключевое слово delegate. Скажем, у нас есть определение делегата, которое выглядит так:

public delegate bool NotifyFriendsDelegate(int intensity);

В основном это говорит о том, что любой метод (где угодно), который возвращает логическое значение, и принимает один параметр типа int, является экземпляром этого делегата. Таким образом, определение делегата определяет форму или подпись, которые должны соответствовать этим методам.

Тогда скажем, что у нас есть класс:

public class MyCar
{

   public bool GoVisitMyFriends(NotifyFriendsDelegate thingToDoWhenWeGetThere)
   {
         var doOurFriendsLikeUs = false;
         var driving = new DrivingClass();
         var didWeGetThere = driving.DoTheDrivingNowPlease();

         if(didWeGetThere)
         {
              doOurFriendsLikeUs = thingToDoWhenWeGetThere(11);
         } 
         return doOurFriendsLikeUs;
   }
}

Этот класс представляет собой вымышленный автомобиль, и у него есть простой способ, который заставляет машину ехать в наш дом друзей. Если автомобиль добирается до дома наших друзей, мы хотим уведомить наших друзей о том, что мы прибыли... но класс автомобиля не знает точно, как уведомить наших друзей. Мы могли бы сыграть стерео на самом деле громко, мы могли бы выпустить рог, или мы могли бы использовать бык.

Так как метод GoVisitMyFriends не знает, как точно уведомить наших друзей, вместо этого он требует, чтобы вызывающий код передавал ссылку на какой-либо метод, который может выполнять часть уведомления. GoVisitMyFriends не заботится о том, какой метод вы ему даете, если метод имеет форму так же, как определение NotifyFriendsDelegate (он должен возвращать логическое значение и принимать один параметр типа int).

Теперь давайте создадим простой класс, который использует наш вымышленный автомобиль:

public class MyFunClass()
{
    public bool NotifyFriendsByRammingTheirHouse(int howHard)
    {
         var rammingModule = new RammingModule();
         return rammingModule.RamFriendsHouse(howHard); 
    }

    public bool DoSomethingFun()
    {
         var car = new MyCar();
         var areWeCool = car.GoVisitMyFriends(NotifyFriendsByRammingTheirHouse);
         return areWeCool;
    }
} 

Этот класс содержит метод, который соответствует сигнатуре NotifyFriendsDelegate. Он содержит метод DoSomethingFun, который создает экземпляр MyCar, затем вызывает метод GoVisitMyFriends. И он проходит в методе NotifyFriendsByRammingTheirHouse, так что класс MyCar будет знать, как мы хотим показать свою любовь к нашим друзьям, когда мы туда доберемся.

И что простейшая форма использования делегата я могу придумать.

BTW: Мне всегда было полезно думать о событиях как о специальных переменных, которые содержат коллекцию методов делегатов. Событию может быть присвоено любое число (от нуля до бесконечности) делегатов, все из которых будут вызываться при вызове события. События - это просто группы делегатов, которые можно рассматривать как "одно".

Ответ 4

Взгляните на руководство по программированию на С# - здесь - это раздел делегатов.