Возможный дубликат:
В чем разница между делегатом и событиями?
Этот вопрос я получил в интервью, и я до сих пор не знаю, каким должен быть ответ.
Я был бы признателен за любые мысли!
Возможный дубликат:
В чем разница между делегатом и событиями?
Этот вопрос я получил в интервью, и я до сих пор не знаю, каким должен быть ответ.
Я был бы признателен за любые мысли!
У меня article в точности точно
Вкратце, вы можете думать о том, что событие немного похоже на свойство, но вместо того, чтобы иметь операции get/set, оно добавляет/удаляет. Добавляемое/удаляемое значение всегда является ссылкой делегата.
Делегаты сами поддерживают операции:
Обратите внимание, что сами делегаты неизменяемы, поэтому операции объединения/удаления возвращают новый экземпляр делегата вместо изменения существующих.
Остальные ответы до сих пор неплохие. Вот еще один способ подумать об этом.
Какова семантическая разница между свойством и полем? Я не имею в виду, каковы технические отличия, как свойство на самом деле пара методов, бла-бла-бла. Я имею в виду, насколько понимается смысл программы, в чем разница?
Свойство обычно является публичным членом класса и представляет собой свойство моделируемой модели. То есть, вы хотите создать модель газеты, чтобы сделать классную газету, и вы дадите ей собственность издателя. Издатель является собственностью газет, поэтому Издатель является свойством класса Газета.
Поле обычно представляет собой элемент реализации класса. Возможно, свойство Publisher фактически реализовано как поле. Но в газетах нет "полей", поэтому вы не публикуете поле издателя в качестве публичного участника класса "Газета"; вы используете его как частную деталь реализации свойства Publisher.
События и делегаты несколько аналогичны. Событие - это что-то в модели. Кнопка - это вещь, которая может сообщить вам, когда она нажата, поэтому класс Button имеет событие "Click". Делегат, который фактически информирует, представляет собой деталь реализации события.
В принципе, делегат - это просто оболочка вокруг того, что было бы указателем функции в C (или списком указателей на функции).
Событие представляет собой еще более высокую абстракцию уровня, которая обертывает концепцию делегата вместе с методами подписки и отмены подписки метода на таких делегатов.
Событие - это свойство, которое предоставляет метод add
и remove
(вызывается через +=
и -=
в коде) для добавления/удаления подписчиков в список делегатов.
Я с готовностью признаю, что этот ответ не сравнивает разницу между делегатами и событиями. Тем не менее, я думаю, что с ответами, которые другие дали для "События", с более подробным объяснением делегатов, вы увидите разницу между ними. Более конкретно, как только у вас будет более четкое понимание делегатов, я думаю, вы получите концептуальную разницу между делегатами и событиями.
Что помогло мне понять, что такое делегат, думает о них как о контейнере для одного метода.
Чтобы концептуализировать, как делегат является "контейнером" метода, просмотрите этот пример, который использует делегат для вызова трех разных методов. Обратите внимание: хотя один и тот же экземпляр делегата используется для вызова трех разных методов, экземпляр делегата будет содержать (или целевой) один метод в любой момент времени.
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() просто получает список делегатов, затем вызывает метод. Этот дизайн очень похож на то, как мы реализуем интерфейсы.
Подробнее о Когда использовать делегаты вместо интерфейсов
Делегат похож на указатель на функцию в C/С++. Он содержит ссылку на метод и экземпляр объекта (если метод нестатический). Делегаты обычно многоадресны, т.е. Содержат ссылки на несколько пар объектов/методов.
Событие - это механизм уведомления, основанный на делегатах. Единственное, что публично раскрывает, это пара методов (добавление/удаление) для подписки на подписку или отписки от уведомления. Тип делегата используется для определения сигнатуры методов обработчика, а список подписчиков (обычно) хранится внутри себя как делегат.
Здесь действительно хорошая статья.
http://www.akadia.com/services/dotnet_delegates_and_events.html
В принципе, события предусматривают строго связанную парадигму подписки на подписку, в то время как делегаты обеспечивают гораздо более слабосвязанный дизайн.
События проще и проще использовать.
Делегаты - это не что иное, как указатель на функцию, где функция вызывается асинхронно. Но события - это не что иное, как уведомление. Например, нажатие кнопки - это событие, поэтому для этого вам нужно подписаться на событие нажатия кнопки и т.д.