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

В чем разница между делегатом и событием в С#?

Возможный дубликат:
В чем разница между делегатом и событиями?

Этот вопрос я получил в интервью, и я до сих пор не знаю, каким должен быть ответ.
Я был бы признателен за любые мысли!

4b9b3361

Ответ 1

У меня article в точности точно

Вкратце, вы можете думать о том, что событие немного похоже на свойство, но вместо того, чтобы иметь операции get/set, оно добавляет/удаляет. Добавляемое/удаляемое значение всегда является ссылкой делегата.

Делегаты сами поддерживают операции:

  • Объединить (объединить несколько экземпляров делегата вместе)
  • Удалить (разделить их снова)
  • Вызов (синхронный или асинхронный)
  • Различные вещи, связанные с поиском цели, списком вызовов и т.д.

Обратите внимание, что сами делегаты неизменяемы, поэтому операции объединения/удаления возвращают новый экземпляр делегата вместо изменения существующих.

Ответ 2

Остальные ответы до сих пор неплохие. Вот еще один способ подумать об этом.

Какова семантическая разница между свойством и полем? Я не имею в виду, каковы технические отличия, как свойство на самом деле пара методов, бла-бла-бла. Я имею в виду, насколько понимается смысл программы, в чем разница?

Свойство обычно является публичным членом класса и представляет собой свойство моделируемой модели. То есть, вы хотите создать модель газеты, чтобы сделать классную газету, и вы дадите ей собственность издателя. Издатель является собственностью газет, поэтому Издатель является свойством класса Газета.

Поле обычно представляет собой элемент реализации класса. Возможно, свойство Publisher фактически реализовано как поле. Но в газетах нет "полей", поэтому вы не публикуете поле издателя в качестве публичного участника класса "Газета"; вы используете его как частную деталь реализации свойства Publisher.

События и делегаты несколько аналогичны. Событие - это что-то в модели. Кнопка - это вещь, которая может сообщить вам, когда она нажата, поэтому класс Button имеет событие "Click". Делегат, который фактически информирует, представляет собой деталь реализации события.

Ответ 3

В принципе, делегат - это просто оболочка вокруг того, что было бы указателем функции в C (или списком указателей на функции).

Событие представляет собой еще более высокую абстракцию уровня, которая обертывает концепцию делегата вместе с методами подписки и отмены подписки метода на таких делегатов.

Событие - это свойство, которое предоставляет метод add и remove (вызывается через += и -= в коде) для добавления/удаления подписчиков в список делегатов.

Ответ 4

Я с готовностью признаю, что этот ответ не сравнивает разницу между делегатами и событиями. Тем не менее, я думаю, что с ответами, которые другие дали для "События", с более подробным объяснением делегатов, вы увидите разницу между ними. Более конкретно, как только у вас будет более четкое понимание делегатов, я думаю, вы получите концептуальную разницу между делегатами и событиями.

Что помогло мне понять, что такое делегат, думает о них как о контейнере для одного метода.

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

class Program
{
    delegate void MyDelegate();

    static void Main()
    {            
        //Notice how we use the same delegate instance
        //to target different methods of the same signature

        MyDelegate myDelegate = new MyDelegate(MethodA);
        myDelegate(); //Invoke the method
        myDelegate = MethodB;
        myDelegate();
        myDelegate = MyClass.MethodZ;
        myDelegate();

        Console.ReadLine();
    }

    static void MethodA()
    {
        Console.WriteLine("Method 'A' is doing work.");
    }

    static void MethodB()
    {
        Console.WriteLine("Method 'B' is doing work.");
    }

    class MyClass
    {
        public static void MethodZ()
        {
            Console.WriteLine("Method 'Z' of MyClass is doing work");
        }
    }
}

Вы заметите, что делегат в примере может содержать/задавать любой метод, который имеет ту же подпись, что и делегат (возвращает void и принимает нулевые параметры в нашем примере). Если вы остановитесь здесь и переварите этот принцип, вы отлично поймете, что понимаете делегатов.

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

static void Main()
{
    MethodA();
    MethodB();
    MyClass.MethodZ();

    Console.ReadLine();
}

Итак, что является примером того, когда мы будем реализовывать делегат явно? Джон Скит помог мне ответить на этот вопрос, когда сказал он

... вы можете представить тип делегата как будучи немного похожим на интерфейс с единый метод.

Зная, что делегат является контейнером для метода, и теперь, учитывая, что делегат подобен интерфейсу с единственным методом, рассмотрим следующее:

Скажем, у нас есть программа, которая запустит двигатели различных типов автомобилей - Car, Motorcyle и Airplane.

Наша программа будет состоять из классов автомобилей - по одному классу для каждого типа транспортного средства. Каждый класс автомобиля несет ответственность за запуск собственного двигателя. Кроме того, подобно реализации интерфейса, каждый класс будет следить за тем, чтобы его метод, который запускает собственный движок, будет иметь указанную подпись, которую согласуют все другие классы (и Main).

Итак, у нас есть что-то вроде этого:

class VehicleProgram
{
    //All vehicle classes implement their own engine starter method that has this signature
    delegate void StartEngine();
    static void Main()
    {
        //The Main doesn't know the details of starting an engine.
        //It delegates the responsibility to the concrete vehicle class
        foreach (StartEngine starter in GetVehicleStarters())
        {
            starter(); //Invoke the method
        }

        Console.ReadLine();
    }

    static List<StartEngine> GetVehicleStarters()
    {
        //Create a list of delegates that target the engine starter methods
        List<StartEngine> starters = new List<StartEngine>();

        starters.Add(Car.StartCar);
        starters.Add(Motorcycle.StartMotorcycle);
        starters.Add(Airplane.StartAirplane);

        return (starters);
    }

    class Car
    {
        public static void StartCar()
        {
            Console.WriteLine("The car is starting.");
        }
    }

    class Motorcycle
    {
        public static void StartMotorcycle()
        {
            Console.WriteLine("The motorcycle is starting.");
        }
    }

    class Airplane
    {
        public static void StartAirplane()
        {
            Console.WriteLine("The airplane is starting.");
        }
    }
}

Поскольку делегаты имеют методы, мы смогли реализовать проект, в котором Main() просто получает список делегатов, затем вызывает метод. Этот дизайн очень похож на то, как мы реализуем интерфейсы.

Подробнее о Когда использовать делегаты вместо интерфейсов

Ответ 5

Делегат похож на указатель на функцию в C/С++. Он содержит ссылку на метод и экземпляр объекта (если метод нестатический). Делегаты обычно многоадресны, т.е. Содержат ссылки на несколько пар объектов/методов.

Событие - это механизм уведомления, основанный на делегатах. Единственное, что публично раскрывает, это пара методов (добавление/удаление) для подписки на подписку или отписки от уведомления. Тип делегата используется для определения сигнатуры методов обработчика, а список подписчиков (обычно) хранится внутри себя как делегат.

Ответ 6

Здесь действительно хорошая статья.

http://www.akadia.com/services/dotnet_delegates_and_events.html

В принципе, события предусматривают строго связанную парадигму подписки на подписку, в то время как делегаты обеспечивают гораздо более слабосвязанный дизайн.

События проще и проще использовать.

Ответ 7

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